diff --git a/.image/common/erp-feature.png b/.image/common/erp-feature.png new file mode 100644 index 000000000..d30b30eed Binary files /dev/null and b/.image/common/erp-feature.png differ diff --git a/README.md b/README.md index 56eeefbf2..296df47ec 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,8 @@ * 数据报表 * 商城系统 * 微信公众号 +* ERP 系统 +* CRM 系统 > 友情提示:本项目基于 RuoYi-Vue 修改,**重构优化**后端的代码,**美化**前端的界面。 > @@ -247,23 +249,31 @@ | 🚀 | 会员分组 | 对会员进行分组,用于用户画像、内容推送等运营手段 | | 🚀 | 积分签到 | 回馈给签到、消费等行为的积分,会员可订单抵现、积分兑换等途径消耗 | +### ERP 系统 + +![功能图](/.image/common/erp-feature.png) + +演示地址: + ## 🐨 技术栈 ### 模块 -| 项目 | 说明 | -|--------------------------------------------------------------------------|--------------------| -| `yudao-dependencies` | Maven 依赖版本管理 | -| `yudao-framework` | Java 框架拓展 | -| `yudao-server` | 管理后台 + 用户 APP 的服务端 | -| `yudao-module-system` | 系统功能的 Module 模块 | -| `yudao-module-member` | 会员中心的 Module 模块 | -| `yudao-module-infra` | 基础设施的 Module 模块 | -| `yudao-module-bpm` | 工作流程的 Module 模块 | -| `yudao-module-pay` | 支付系统的 Module 模块 | -| `yudao-module-mall` | 商城系统的 Module 模块 | -| `yudao-module-mp` | 微信公众号的 Module 模块 | -| `yudao-module-report` | 大屏报表 Module 模块 | +| 项目 | 说明 | +|-----------------------|--------------------| +| `yudao-dependencies` | Maven 依赖版本管理 | +| `yudao-framework` | Java 框架拓展 | +| `yudao-server` | 管理后台 + 用户 APP 的服务端 | +| `yudao-module-system` | 系统功能的 Module 模块 | +| `yudao-module-member` | 会员中心的 Module 模块 | +| `yudao-module-infra` | 基础设施的 Module 模块 | +| `yudao-module-bpm` | 工作流程的 Module 模块 | +| `yudao-module-pay` | 支付系统的 Module 模块 | +| `yudao-module-mall` | 商城系统的 Module 模块 | +| `yudao-module-erp` | ERP 系统的 Module 模块 | +| `yudao-module-crm` | CRM 系统的 Module 模块 | +| `yudao-module-mp` | 微信公众号的 Module 模块 | +| `yudao-module-report` | 大屏报表 Module 模块 | ### 框架 diff --git a/pom.xml b/pom.xml index 93251fd1a..16382ecb4 100644 --- a/pom.xml +++ b/pom.xml @@ -15,13 +15,14 @@ yudao-module-system yudao-module-infra - + yudao-module-member + @@ -31,7 +32,7 @@ https://github.com/YunaiV/ruoyi-vue-pro - 2.0.0-jdk8-snapshot + 2.0.1-jdk8-snapshot 1.8 ${java.version} diff --git a/script/shell/deploy.sh b/script/shell/deploy.sh index f0fdf1fe6..b635a70b8 100644 --- a/script/shell/deploy.sh +++ b/script/shell/deploy.sh @@ -74,7 +74,7 @@ function stop() { if [ -n "$PID" ]; then echo -e ".\c" else - echo '[stop] 停止 $BASE_PATH/$SERVER_NAME 成功' + echo "[stop] 停止 $BASE_PATH/$SERVER_NAME 成功" break fi done diff --git a/sql/mysql/ruoyi-vue-pro.sql b/sql/mysql/ruoyi-vue-pro.sql index 0a01aa9dc..3306b7c72 100644 --- a/sql/mysql/ruoyi-vue-pro.sql +++ b/sql/mysql/ruoyi-vue-pro.sql @@ -11,7 +11,7 @@ Target Server Version : 80200 (8.2.0) File Encoding : 65001 - Date: 26/01/2024 20:11:43 + Date: 17/02/2024 21:00:07 */ SET NAMES utf8mb4; @@ -385,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 = 15093 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; +) ENGINE = InnoDB AUTO_INCREMENT = 15324 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; -- ---------------------------- -- Records of infra_api_error_log @@ -423,7 +423,7 @@ CREATE TABLE `infra_codegen_column` ( `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 = 2015 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义'; +) ENGINE = InnoDB AUTO_INCREMENT = 2248 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义'; -- ---------------------------- -- Records of infra_codegen_column @@ -461,7 +461,7 @@ CREATE TABLE `infra_codegen_table` ( `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 = 156 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义'; +) ENGINE = InnoDB AUTO_INCREMENT = 171 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义'; -- ---------------------------- -- Records of infra_codegen_table @@ -690,7 +690,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 = 1242 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1261 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; -- ---------------------------- -- Records of infra_file @@ -879,7 +879,7 @@ CREATE TABLE `system_dict_data` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1486 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1508 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表'; -- ---------------------------- -- Records of system_dict_data @@ -1236,6 +1236,28 @@ 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 (1483, 3, '转账成功', '20', 'pay_transfer_status', 0, 'success', '', '', '1', '2023-10-28 16:23:50', '1', '2023-10-28 16:23:50', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1484, 2, '转账进行中', '10', 'pay_transfer_status', 0, 'info', '', '', '1', '2023-10-28 16:23:12', '1', '2023-10-28 16:23: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 (1485, 1, '等待转账', '0', 'pay_transfer_status', 0, 'default', '', '', '1', '2023-10-28 16:21:43', '1', '2023-10-28 16:23: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 (1486, 10, '其它入库', '10', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-05 18:07:25', '1', '2024-02-05 18:07: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 (1487, 11, '其它入库(作废)', '11', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-05 18:08:07', '1', '2024-02-05 19:20: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 (1488, 20, '其它出库', '20', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-05 18:08:51', '1', '2024-02-05 18:08:51', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1489, 21, '其它出库(作废)', '21', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-05 18:09:00', '1', '2024-02-05 19:20:10', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1490, 10, '未审核', '10', 'erp_audit_status', 0, 'default', '', '', '1', '2024-02-06 00:00:21', '1', '2024-02-06 00:00: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 (1491, 20, '已审核', '20', 'erp_audit_status', 0, 'success', '', '', '1', '2024-02-06 00:00:35', '1', '2024-02-06 00:00: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 (1492, 30, '调拨入库', '30', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-07 20:34:19', '1', '2024-02-07 12:36:31', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1493, 31, '调拨入库(作废)', '31', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-07 20:34:29', '1', '2024-02-07 20:37:11', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1494, 32, '调拨出库', '32', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-07 20:34:38', '1', '2024-02-07 12:36: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 (1495, 33, '调拨出库(作废)', '33', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-07 20:34:49', '1', '2024-02-07 20:37:06', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1496, 40, '盘盈入库', '40', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-08 08:53:00', '1', '2024-02-08 08:53:09', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1497, 41, '盘盈入库(作废)', '41', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-08 08:53:39', '1', '2024-02-16 19:40: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 (1498, 42, '盘亏出库', '42', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-08 08:54:16', '1', '2024-02-08 08:54: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 (1499, 43, '盘亏出库(作废)', '43', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-08 08:54:31', '1', '2024-02-16 19:40:46', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1500, 50, '销售出库', '50', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-11 21:47:25', '1', '2024-02-11 21:50:40', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1501, 51, '销售出库(作废)', '51', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-11 21:47:37', '1', '2024-02-11 21:51: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 (1502, 60, '销售退货入库', '60', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-12 06:51:05', '1', '2024-02-12 06:51: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 (1503, 61, '销售退货入库(作废)', '61', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-12 06:51:18', '1', '2024-02-12 06:51: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 (1504, 70, '采购入库', '70', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-16 13:10:02', '1', '2024-02-16 13:10:02', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1505, 71, '采购入库(作废)', '71', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-16 13:10:10', '1', '2024-02-16 19:40:40', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1506, 80, '采购退货出库', '80', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-16 13:10:17', '1', '2024-02-16 13:10:17', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1507, 81, '采购退货出库(作废)', '81', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-16 13:10:26', '1', '2024-02-16 19:40:33', b'0'); COMMIT; -- ---------------------------- @@ -1256,7 +1278,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 = 611 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表'; +) ENGINE = InnoDB AUTO_INCREMENT = 613 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表'; -- ---------------------------- -- Records of system_dict_type @@ -1343,6 +1365,8 @@ 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 (608, 'CRM 跟进方式', 'crm_follow_up_type', 0, '', '1', '2024-01-15 20:48:05', '1', '2024-01-15 20:48:05', 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 (609, '支付转账类型', 'pay_transfer_type', 0, '', '1', '2023-10-28 16:27:18', '1', '2023-10-28 16:27:18', 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 (610, '转账订单状态', 'pay_transfer_status', 0, '', '1', '2023-10-28 16:18:32', '1', '2023-10-28 16:18:32', 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 (611, 'ERP 库存明细的业务类型', 'erp_stock_record_biz_type', 0, 'ERP 库存明细的业务类型', '1', '2024-02-05 18:07:02', '1', '2024-02-05 18:07:02', 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 (612, 'ERP 审批状态', 'erp_audit_status', 0, '', '1', '2024-02-06 00:00:07', '1', '2024-02-06 00:00:07', b'0', '1970-01-01 00:00:00'); COMMIT; -- ---------------------------- @@ -1391,7 +1415,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 = 2861 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; +) ENGINE = InnoDB AUTO_INCREMENT = 2906 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; -- ---------------------------- -- Records of system_login_log @@ -1521,7 +1545,7 @@ CREATE TABLE `system_menu` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 2560 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表'; +) ENGINE = InnoDB AUTO_INCREMENT = 2702 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表'; -- ---------------------------- -- Records of system_menu @@ -2013,44 +2037,44 @@ 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', '2024-01-15 21:27:42', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2391, '客户管理', '', 2, 10, 2397, 'customer', 'fa:address-book-o', 'crm/customer/index', 'CrmCustomer', 0, b'1', b'1', b'1', '', '2023-10-29 09:04:21', '1', '2024-02-17 17:13: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 (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 (2397, 'CRM 系统', '', 1, 200, 0, '/crm', 'ep:avatar', '', '', 0, b'1', b'1', b'1', '1', '2023-10-29 17:08:30', '1', '2024-02-04 15:37:31', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2398, '合同管理', '', 2, 50, 2397, 'contract', 'ep:notebook', 'crm/contract/index', 'CrmContract', 0, b'1', b'1', b'1', '', '2023-10-29 10:50:41', '1', '2024-02-17 17:15: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 (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 (2404, '线索管理', '', 2, 8, 2397, 'clue', 'fa:pagelines', 'crm/clue/index', 'CrmClue', 0, b'1', b'1', b'1', '', '2023-10-29 11:06:29', '1', '2024-02-17 17:15:41', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (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 (2410, '商机管理', '', 2, 40, 2397, 'business', 'fa:bus', 'crm/business/index', 'CrmBusiness', 0, b'1', b'1', b'1', '', '2023-10-29 11:12:35', '1', '2024-02-17 17:14:55', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (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', 'CrmContact', 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '1', '2023-12-01 19:39:50', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2416, '联系人管理', '', 2, 20, 2397, 'contact', 'fa:address-book-o', 'crm/contact/index', 'CrmContact', 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '1', '2024-02-17 17:13: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 (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 (2422, '回款管理', '', 2, 60, 2397, 'receivable', 'ep:money', 'crm/receivable/index', 'CrmReceivable', 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '1', '2024-02-17 17:16:18', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (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/receivable/plan/index', 'CrmReceivablePlan', 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '1', '2023-12-01 19:55:48', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2428, '回款计划', '', 2, 61, 2397, 'receivable-plan', 'fa:money', 'crm/receivable/plan/index', 'CrmReceivablePlan', 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '1', '2024-02-17 17:16:11', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (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'); @@ -2103,7 +2127,7 @@ 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 (2521, '客户限制配置更新', 'crm:customer-limit-config:update', 3, 3, 2518, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-18 13:33:53', '', '2023-11-18 13:33: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 (2522, '客户限制配置删除', 'crm:customer-limit-config:delete', 3, 4, 2518, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-18 13:33:53', '', '2023-11-18 13:33: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 (2523, '客户限制配置导出', 'crm:customer-limit-config:export', 3, 5, 2518, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-18 13:33:53', '', '2023-11-18 13:33: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 (2524, '系统配置', '', 1, 99, 2397, 'config', 'ep:connection', '', '', 0, b'1', b'1', b'1', '1', '2023-11-18 21:58:00', '1', '2023-11-18 21:58:00', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2524, '系统配置', '', 1, 999, 2397, 'config', 'ep:connection', '', '', 0, b'1', b'1', b'1', '1', '2023-11-18 21:58:00', '1', '2024-02-17 17:14:34', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2525, 'WebSocket 测试', '', 2, 7, 2, 'websocket', 'ep:connection', 'infra/webSocket/index', 'InfraWebSocket', 0, b'1', b'1', b'1', '1', '2023-11-23 19:41:55', '1', '2023-11-24 19:22: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 (2526, '产品管理', '', 2, 10, 2397, 'product', 'fa:product-hunt', 'crm/product/index', 'CrmProduct', 0, b'1', b'1', b'1', '1', '2023-12-05 22:45:26', '1', '2023-12-05 22:46:45', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2527, '产品查询', 'crm:product:query', 3, 1, 2526, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-12-05 22:47:16', '1', '2023-12-05 22:47:16', b'0'); @@ -2125,7 +2149,7 @@ 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 (2543, '关联商机', 'crm:contact:create-business', 3, 10, 2416, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-01-02 17:28:25', '1', '2024-01-02 17:28:25', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2544, '取关商机', 'crm:contact:delete-business', 3, 11, 2416, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-01-02 17:28:43', '1', '2024-01-02 17:28: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 (2545, '商品统计', '', 2, 3, 2358, 'product', 'fa:product-hunt', 'statistics/product/index', 'ProductStatistics', 0, b'1', b'1', b'1', '', '2023-12-15 18:54:28', '1', '2024-01-17 23:11:54', b'0'); -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2546, '客户公海', '', 2, -1, 2397, 'customer/pool', 'fa-solid:swimming-pool', 'crm/customer/pool/index', 'CrmCustomerPool', 0, b'1', b'1', b'1', '1', '2024-01-15 21:29:34', '1', '2023-12-29 19:47: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 (2546, '客户公海', '', 2, 30, 2397, 'customer/pool', 'fa-solid:swimming-pool', 'crm/customer/pool/index', 'CrmCustomerPool', 0, b'1', b'1', b'1', '1', '2024-01-15 21:29:34', '1', '2024-02-17 17:14:18', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2547, '订单查询', 'trade:order:query', 3, 1, 2076, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-01-16 08:52:00', '1', '2024-01-16 08:52:00', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2548, '订单更新', 'trade:order:update', 3, 2, 2076, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-01-16 08:52:21', '1', '2024-01-16 08:52: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 (2549, '支付&退款案例', '', 2, 1, 2161, 'order', 'fa:paypal', 'pay/demo/order/index', '', 0, b'1', b'1', b'1', '1', '2024-01-18 23:45:00', '1', '2024-01-18 23:47:21', b'0'); @@ -2139,6 +2163,148 @@ 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 (2557, '钱包余额', '', 2, 1, 2551, 'wallet-balance', 'fa:leaf', 'pay/wallet/balance/index', 'WalletBalance', 0, b'1', b'1', b'1', '', '2023-12-29 02:32:54', '', '2023-12-29 02:32:54', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2558, '钱包余额查询', 'pay:wallet:query', 3, 1, 2557, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-12-29 02:32:54', '', '2023-12-29 02:32:54', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2559, '转账订单', '', 2, 3, 1117, 'transfer', 'ep:credit-card', 'pay/transfer/index', 'PayTransfer', 0, b'1', b'1', b'1', '', '2023-12-29 02:32:54', '', '2023-12-29 02:32:54', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2560, '商业智能', '', 1, 200, 2397, 'bi', 'ep:data-line', '', '', 0, b'1', b'1', b'1', '1', '2024-01-26 22:50:35', '1', '2024-02-17 17:14:39', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2561, '排行榜', '', 2, 1, 2560, 'ranking', 'fa:area-chart', 'crm/bi/rank/index', 'BiRanking', 0, b'1', b'1', b'1', '1', '2024-01-26 22:52:09', '1', '2024-02-03 01:10:43', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2562, '客户导入', 'crm:customer:import', 3, 6, 2391, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-02-01 13:09:00', '1', '2024-02-01 13:09:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2563, 'ERP 系统', '', 1, 300, 0, '/erp', 'fa-solid:store', '', '', 0, b'1', b'1', b'1', '1', '2024-02-04 15:37:25', '1', '2024-02-04 15:37:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2564, '产品管理', '', 1, 40, 2563, 'product', 'fa:product-hunt', '', '', 0, b'1', b'1', b'1', '1', '2024-02-04 15:38:43', '1', '2024-02-04 15:38:43', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2565, '产品信息', '', 2, 0, 2564, 'product', 'fa-solid:apple-alt', 'erp/product/product/index', 'ErpProduct', 0, b'1', b'1', b'1', '', '2024-02-04 07:52:15', '1', '2024-02-05 14:42:11', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2566, '产品查询', 'erp:product:query', 3, 1, 2565, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-02-04 07:52:15', '1', '2024-02-04 17:21:57', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2567, '产品创建', 'erp:product:create', 3, 2, 2565, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-02-04 07:52:15', '1', '2024-02-04 17:22:12', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2568, '产品更新', 'erp:product:update', 3, 3, 2565, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-02-04 07:52:15', '1', '2024-02-04 17:22:16', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2569, '产品删除', 'erp:product:delete', 3, 4, 2565, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-02-04 07:52:15', '1', '2024-02-04 17:22:22', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2570, '产品导出', 'erp:product:export', 3, 5, 2565, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-02-04 07:52:15', '1', '2024-02-04 17:22:26', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2571, '产品分类', '', 2, 1, 2564, 'product-category', 'fa:certificate', 'erp/product/category/index', 'ErpProductCategory', 0, b'1', b'1', b'1', '', '2024-02-04 09:21:04', '1', '2024-02-04 17:24:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2572, '分类查询', 'erp:product-category:query', 3, 1, 2571, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 09:21:04', '', '2024-02-04 09:21:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2573, '分类创建', 'erp:product-category:create', 3, 2, 2571, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 09:21:04', '', '2024-02-04 09:21:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2574, '分类更新', 'erp:product-category:update', 3, 3, 2571, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 09:21:04', '', '2024-02-04 09:21:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2575, '分类删除', 'erp:product-category:delete', 3, 4, 2571, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 09:21:04', '', '2024-02-04 09:21:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2576, '分类导出', 'erp:product-category:export', 3, 5, 2571, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 09:21:04', '', '2024-02-04 09:21:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2577, '产品单位', '', 2, 2, 2564, 'unit', 'ep:opportunity', 'erp/product/unit/index', 'ErpProductUnit', 0, b'1', b'1', b'1', '', '2024-02-04 11:54:08', '1', '2024-02-04 19:54:37', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2578, '单位查询', 'erp:product-unit:query', 3, 1, 2577, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 11:54:08', '', '2024-02-04 11:54: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 (2579, '单位创建', 'erp:product-unit:create', 3, 2, 2577, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 11:54:08', '', '2024-02-04 11:54: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 (2580, '单位更新', 'erp:product-unit:update', 3, 3, 2577, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 11:54:08', '', '2024-02-04 11:54: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 (2581, '单位删除', 'erp:product-unit:delete', 3, 4, 2577, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 11:54:08', '', '2024-02-04 11:54: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 (2582, '单位导出', 'erp:product-unit:export', 3, 5, 2577, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 11:54:08', '', '2024-02-04 11:54: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 (2583, '库存管理', '', 1, 30, 2563, 'stock', 'fa:window-restore', '', '', 0, b'1', b'1', b'1', '1', '2024-02-05 00:29:37', '1', '2024-02-05 00:29:37', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2584, '仓库信息', '', 2, 0, 2583, 'warehouse', 'ep:house', 'erp/stock/warehouse/index', 'ErpWarehouse', 0, b'1', b'1', b'1', '', '2024-02-04 17:12:09', '1', '2024-02-05 01:12: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 (2585, '仓库查询', 'erp:warehouse:query', 3, 1, 2584, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 17:12:09', '', '2024-02-04 17:12: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 (2586, '仓库创建', 'erp:warehouse:create', 3, 2, 2584, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 17:12:09', '', '2024-02-04 17:12: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 (2587, '仓库更新', 'erp:warehouse:update', 3, 3, 2584, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 17:12:09', '', '2024-02-04 17:12: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 (2588, '仓库删除', 'erp:warehouse:delete', 3, 4, 2584, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 17:12:09', '', '2024-02-04 17:12: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 (2589, '仓库导出', 'erp:warehouse:export', 3, 5, 2584, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 17:12:09', '', '2024-02-04 17:12: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 (2590, '产品库存', '', 2, 1, 2583, 'stock', 'ep:coffee', 'erp/stock/stock/index', 'ErpStock', 0, b'1', b'1', b'1', '', '2024-02-05 06:40:50', '1', '2024-02-05 14:42:44', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2591, '库存查询', 'erp:stock:query', 3, 1, 2590, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 06:40:50', '', '2024-02-05 06:40:50', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2592, '库存导出', 'erp:stock:export', 3, 5, 2590, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 06:40:50', '', '2024-02-05 06:40:50', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2593, '出入库明细', '', 2, 2, 2583, 'record', 'fa-solid:blog', 'erp/stock/record/index', 'ErpStockRecord', 0, b'1', b'1', b'1', '', '2024-02-05 10:27:21', '1', '2024-02-06 17:26:11', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2594, '库存明细查询', 'erp:stock-record:query', 3, 1, 2593, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 10:27:21', '', '2024-02-05 10:27: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 (2595, '库存明细导出', 'erp:stock-record:export', 3, 5, 2593, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 10:27:21', '', '2024-02-05 10:27: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 (2596, '其它入库', '', 2, 3, 2583, 'in', 'ep:zoom-in', 'erp/stock/in/index', 'ErpStockIn', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-07 19:06: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 (2597, '其它入库单查询', 'erp:stock-in:query', 3, 1, 2596, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-05 16:08: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 (2598, '其它入库单创建', 'erp:stock-in:create', 3, 2, 2596, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-05 16:08: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 (2599, '其它入库单更新', 'erp:stock-in:update', 3, 3, 2596, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-05 16:08: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 (2600, '其它入库单删除', 'erp:stock-in:delete', 3, 4, 2596, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-05 16:08: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 (2601, '其它入库单导出', 'erp:stock-in:export', 3, 5, 2596, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-05 16:08: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 (2602, '采购管理', '', 1, 10, 2563, 'purchase', 'fa:buysellads', '', '', 0, b'1', b'1', b'1', '1', '2024-02-06 16:01:01', '1', '2024-02-06 16:01:23', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2603, '供应商信息', '', 2, 4, 2602, 'supplier', 'fa:superpowers', 'erp/purchase/supplier/index', 'ErpSupplier', 0, b'1', b'1', b'1', '', '2024-02-06 08:21:55', '1', '2024-02-06 16:22:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2604, '供应商查询', 'erp:supplier:query', 3, 1, 2603, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-06 08:21:55', '', '2024-02-06 08:21:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2605, '供应商创建', 'erp:supplier:create', 3, 2, 2603, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-06 08:21:55', '', '2024-02-06 08:21:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2606, '供应商更新', 'erp:supplier:update', 3, 3, 2603, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-06 08:21:55', '', '2024-02-06 08:21:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2607, '供应商删除', 'erp:supplier:delete', 3, 4, 2603, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-06 08:21:55', '', '2024-02-06 08:21:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2608, '供应商导出', 'erp:supplier:export', 3, 5, 2603, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-06 08:21:55', '', '2024-02-06 08:21:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2609, '其它入库单审批', 'erp:stock-in:update-status', 3, 6, 2596, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-05 16:08: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 (2610, '其它出库', '', 2, 4, 2583, 'out', 'ep:zoom-out', 'erp/stock/out/index', 'ErpStockOut', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-07 19:06:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2611, '其它出库单查询', 'erp:stock-out:query', 3, 1, 2610, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 06:43:39', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2612, '其它出库单创建', 'erp:stock-out:create', 3, 2, 2610, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 06:43:42', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2613, '其它出库单更新', 'erp:stock-out:update', 3, 3, 2610, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 06:43:44', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2614, '其它出库单删除', 'erp:stock-out:delete', 3, 4, 2610, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 06:43: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 (2615, '其它出库单导出', 'erp:stock-out:export', 3, 5, 2610, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 06:43:57', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2616, '其它出库单审批', 'erp:stock-out:update-status', 3, 6, 2610, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 06:43:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2617, '销售管理', '', 1, 20, 2563, 'sale', 'fa:sellsy', '', '', 0, b'1', b'1', b'1', '1', '2024-02-07 15:12:32', '1', '2024-02-07 15:12: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 (2618, '客户信息', '', 2, 4, 2617, 'customer', 'ep:avatar', 'erp/sale/customer/index', 'ErpCustomer', 0, b'1', b'1', b'1', '', '2024-02-07 07:21:45', '1', '2024-02-07 15:22:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2619, '客户查询', 'erp:customer:query', 3, 1, 2618, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-07 07:21:45', '', '2024-02-07 07:21:45', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2620, '客户创建', 'erp:customer:create', 3, 2, 2618, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-07 07:21:45', '', '2024-02-07 07:21:45', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2621, '客户更新', 'erp:customer:update', 3, 3, 2618, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-07 07:21:45', '', '2024-02-07 07:21:45', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2622, '客户删除', 'erp:customer:delete', 3, 4, 2618, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-07 07:21:45', '', '2024-02-07 07:21:45', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2623, '客户导出', 'erp:customer:export', 3, 5, 2618, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-07 07:21:45', '', '2024-02-07 07:21:45', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2624, '库存调拨', '', 2, 5, 2583, 'move', 'ep:folder-remove', 'erp/stock/move/index', 'ErpStockMove', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-16 18:53:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2625, '库存调度单查询', 'erp:stock-move:query', 3, 1, 2624, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12: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 (2626, '库存调度单创建', 'erp:stock-move:create', 3, 2, 2624, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12: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 (2627, '库存调度单更新', 'erp:stock-move:update', 3, 3, 2624, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2628, '库存调度单删除', 'erp:stock-move:delete', 3, 4, 2624, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:57', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2629, '库存调度单导出', 'erp:stock-move:export', 3, 5, 2624, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:59', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2630, '库存调度单审批', 'erp:stock-move:update-status', 3, 6, 2624, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:13: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 (2631, '库存盘点', '', 2, 6, 2583, 'check', 'ep:circle-check-filled', 'erp/stock/check/index', 'ErpStockCheck', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-08 08:31: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 (2632, '库存盘点单查询', 'erp:stock-check:query', 3, 1, 2631, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12: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 (2633, '库存盘点单创建', 'erp:stock-check:create', 3, 2, 2631, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12: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 (2634, '库存盘点单更新', 'erp:stock-check:update', 3, 3, 2631, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2635, '库存盘点单删除', 'erp:stock-check:delete', 3, 4, 2631, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:57', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2636, '库存盘点单导出', 'erp:stock-check:export', 3, 5, 2631, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:59', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2637, '库存盘点单审批', 'erp:stock-check:update-status', 3, 6, 2631, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:13: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 (2638, '销售订单', '', 2, 1, 2617, 'order', 'fa:first-order', 'erp/sale/order/index', 'ErpSaleOrder', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-10 21:59:20', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2639, '销售订单查询', 'erp:sale-order:query', 3, 1, 2638, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12: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 (2640, '销售订单创建', 'erp:sale-order:create', 3, 2, 2638, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12: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 (2641, '销售订单更新', 'erp:sale-order:update', 3, 3, 2638, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2642, '销售订单删除', 'erp:sale-order:delete', 3, 4, 2638, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:57', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2643, '销售订单导出', 'erp:sale-order:export', 3, 5, 2638, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:59', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2644, '销售订单审批', 'erp:sale-order:update-status', 3, 6, 2638, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:13: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 (2645, '财务管理', '', 1, 50, 2563, 'finance', 'ep:money', '', '', 0, b'1', b'1', b'1', '1', '2024-02-10 08:05:58', '1', '2024-02-10 08:06:07', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2646, '结算账户', '', 2, 10, 2645, 'account', 'fa:universal-access', 'erp/finance/account/index', 'ErpAccount', 0, b'1', b'1', b'1', '', '2024-02-10 00:15:07', '1', '2024-02-14 08:24:31', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2647, '结算账户查询', 'erp:account:query', 3, 1, 2646, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-10 00:15:07', '', '2024-02-10 00:15:07', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2648, '结算账户创建', 'erp:account:create', 3, 2, 2646, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-10 00:15:07', '', '2024-02-10 00:15:07', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2649, '结算账户更新', 'erp:account:update', 3, 3, 2646, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-10 00:15:07', '', '2024-02-10 00:15:07', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2650, '结算账户删除', 'erp:account:delete', 3, 4, 2646, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-10 00:15:07', '', '2024-02-10 00:15:07', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2651, '结算账户导出', 'erp:account:export', 3, 5, 2646, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-10 00:15:07', '', '2024-02-10 00:15:07', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2652, '销售出库', '', 2, 2, 2617, 'out', 'ep:sold-out', 'erp/sale/out/index', 'ErpSaleOut', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-10 22:02:07', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2653, '销售出库查询', 'erp:sale-out:query', 3, 1, 2652, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12: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 (2654, '销售出库创建', 'erp:sale-out:create', 3, 2, 2652, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12: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 (2655, '销售出库更新', 'erp:sale-out:update', 3, 3, 2652, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2656, '销售出库删除', 'erp:sale-out:delete', 3, 4, 2652, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:57', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2657, '销售出库导出', 'erp:sale-out:export', 3, 5, 2652, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:59', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2658, '销售出库审批', 'erp:sale-out:update-status', 3, 6, 2652, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:13: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 (2659, '销售退货', '', 2, 3, 2617, 'return', 'fa-solid:bone', 'erp/sale/return/index', 'ErpSaleReturn', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-12 06:12:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2660, '销售退货查询', 'erp:sale-return:query', 3, 1, 2659, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12: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 (2661, '销售退货创建', 'erp:sale-return:create', 3, 2, 2659, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12: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 (2662, '销售退货更新', 'erp:sale-return:update', 3, 3, 2659, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2663, '销售退货删除', 'erp:sale-return:delete', 3, 4, 2659, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:57', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2664, '销售退货导出', 'erp:sale-return:export', 3, 5, 2659, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:59', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2665, '销售退货审批', 'erp:sale-return:update-status', 3, 6, 2659, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:13: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 (2666, '采购订单', '', 2, 1, 2602, 'order', 'fa-solid:border-all', 'erp/purchase/order/index', 'ErpPurchaseOrder', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-12 08:51: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 (2667, '采购订单查询', 'erp:purchase-order:query', 3, 1, 2666, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:17', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2668, '采购订单创建', 'erp:purchase-order:create', 3, 2, 2666, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:54', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2669, '采购订单更新', 'erp:purchase-order:update', 3, 3, 2666, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2670, '采购订单删除', 'erp:purchase-order:delete', 3, 4, 2666, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:00', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2671, '采购订单导出', 'erp:purchase-order:export', 3, 5, 2666, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2672, '采购订单审批', 'erp:purchase-order:update-status', 3, 6, 2666, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45: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 (2673, '采购入库', '', 2, 2, 2602, 'in', 'fa-solid:gopuram', 'erp/purchase/in/index', 'ErpPurchaseIn', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-12 11:19:27', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2674, '采购入库查询', 'erp:purchase-in:query', 3, 1, 2673, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:17', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2675, '采购入库创建', 'erp:purchase-in:create', 3, 2, 2673, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:54', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2676, '采购入库更新', 'erp:purchase-in:update', 3, 3, 2673, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2677, '采购入库删除', 'erp:purchase-in:delete', 3, 4, 2673, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:00', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2678, '采购入库导出', 'erp:purchase-in:export', 3, 5, 2673, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2679, '采购入库审批', 'erp:purchase-in:update-status', 3, 6, 2673, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45: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 (2680, '采购退货', '', 2, 3, 2602, 'return', 'ep:minus', 'erp/purchase/return/index', 'ErpPurchaseReturn', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-12 20:51:02', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2681, '采购退货查询', 'erp:purchase-return:query', 3, 1, 2680, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:17', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2682, '采购退货创建', 'erp:purchase-return:create', 3, 2, 2680, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:54', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2683, '采购退货更新', 'erp:purchase-return:update', 3, 3, 2680, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2684, '采购退货删除', 'erp:purchase-return:delete', 3, 4, 2680, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:00', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2685, '采购退货导出', 'erp:purchase-return:export', 3, 5, 2680, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2686, '采购退货审批', 'erp:purchase-return:update-status', 3, 6, 2680, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45: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 (2687, '付款单', '', 2, 1, 2645, 'payment', 'ep:caret-right', 'erp/finance/payment/index', 'ErpFinancePayment', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-14 08:24:23', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2688, '付款单查询', 'erp:finance-payment:query', 3, 1, 2687, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:17', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2689, '付款单创建', 'erp:finance-payment:create', 3, 2, 2687, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:54', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2690, '付款单更新', 'erp:finance-payment:update', 3, 3, 2687, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2691, '付款单删除', 'erp:finance-payment:delete', 3, 4, 2687, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:00', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2692, '付款单导出', 'erp:finance-payment:export', 3, 5, 2687, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2693, '付款单审批', 'erp:finance-payment:update-status', 3, 6, 2687, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45: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 (2694, '收款单', '', 2, 2, 2645, 'receipt', 'ep:expand', 'erp/finance/receipt/index', 'ErpFinanceReceipt', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-15 19:35:45', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2695, '收款单查询', 'erp:finance-receipt:query', 3, 1, 2694, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:17', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2696, '收款单创建', 'erp:finance-receipt:create', 3, 2, 2694, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:54', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2697, '收款单更新', 'erp:finance-receipt:update', 3, 3, 2694, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2698, '收款单删除', 'erp:finance-receipt:delete', 3, 4, 2694, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:00', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2699, '收款单导出', 'erp:finance-receipt:export', 3, 5, 2694, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2700, '收款单审批', 'erp:finance-receipt:update-status', 3, 6, 2694, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45: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 (2701, '待办事项', '', 2, 0, 2397, 'backlog', 'fa-solid:tasks', 'crm/backlog/index', 'CrmBacklog', 0, b'1', b'1', b'1', '1', '2024-02-17 17:17:11', '1', '2024-02-17 17:17:11', b'0'); COMMIT; -- ---------------------------- @@ -2259,7 +2425,7 @@ CREATE TABLE `system_oauth2_access_token` ( PRIMARY KEY (`id`) USING BTREE, INDEX `idx_access_token`(`access_token` ASC) USING BTREE, INDEX `idx_refresh_token`(`refresh_token` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 4335 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; +) ENGINE = InnoDB AUTO_INCREMENT = 4781 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; -- ---------------------------- -- Records of system_oauth2_access_token @@ -2381,7 +2547,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 = 1309 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; +) ENGINE = InnoDB AUTO_INCREMENT = 1346 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; -- ---------------------------- -- Records of system_oauth2_refresh_token @@ -2421,7 +2587,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 = 9706 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录'; +) ENGINE = InnoDB AUTO_INCREMENT = 10187 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录'; -- ---------------------------- -- Records of system_operate_log @@ -2454,7 +2620,7 @@ CREATE TABLE `system_operate_log_v2` ( `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 = 8888 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录 V2 版本'; +) ENGINE = InnoDB AUTO_INCREMENT = 8892 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录 V2 版本'; -- ---------------------------- -- Records of system_operate_log_v2 @@ -4517,7 +4683,7 @@ CREATE TABLE `system_sms_log` ( `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 = 586 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志'; +) ENGINE = InnoDB AUTO_INCREMENT = 588 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志'; -- ---------------------------- -- Records of system_sms_log @@ -4826,7 +4992,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', '18818260277', 2, 'http://127.0.0.1:48080/admin-api/infra/file/4/get/37e56010ecbee472cdd821ac4b608e151e62a74d9633f15d085aee026eedeb60.png', 0, '0:0:0:0:0:0:0:1', '2024-01-22 21:01:28', 'admin', '2021-01-05 17:03:47', NULL, '2024-01-22 21:01:28', 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', '18818260277', 2, 'http://127.0.0.1:48080/admin-api/infra/file/4/get/37e56010ecbee472cdd821ac4b608e151e62a74d9633f15d085aee026eedeb60.png', 0, '0:0:0:0:0:0:0:1', '2024-02-17 17:10:34', 'admin', '2021-01-05 17:03:47', NULL, '2024-02-17 17:10:34', 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-dependencies/pom.xml b/yudao-dependencies/pom.xml index 61a2def03..4ef58422f 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -14,7 +14,7 @@ https://github.com/YunaiV/ruoyi-vue-pro - 2.0.0-jdk8-snapshot + 2.0.1-jdk8-snapshot 1.5.0 2.7.18 @@ -90,11 +90,6 @@ - - cn.iocoder.boot - yudao-spring-boot-starter-banner - ${revision} - cn.iocoder.boot yudao-spring-boot-starter-biz-operatelog @@ -116,11 +111,6 @@ yudao-spring-boot-starter-biz-dict ${revision} - - cn.iocoder.boot - yudao-spring-boot-starter-biz-sms - ${revision} - cn.iocoder.boot yudao-spring-boot-starter-biz-pay @@ -136,11 +126,6 @@ yudao-spring-boot-starter-biz-data-permission ${revision} - - cn.iocoder.boot - yudao-spring-boot-starter-biz-error-code - ${revision} - cn.iocoder.boot yudao-spring-boot-starter-biz-ip diff --git a/yudao-framework/pom.xml b/yudao-framework/pom.xml index ed1240c5d..a9ef0a5a5 100644 --- a/yudao-framework/pom.xml +++ b/yudao-framework/pom.xml @@ -11,7 +11,6 @@ pom yudao-common - yudao-spring-boot-starter-banner yudao-spring-boot-starter-mybatis yudao-spring-boot-starter-redis yudao-spring-boot-starter-web @@ -27,16 +26,13 @@ yudao-spring-boot-starter-biz-operatelog yudao-spring-boot-starter-biz-dict - yudao-spring-boot-starter-biz-sms yudao-spring-boot-starter-biz-tenant yudao-spring-boot-starter-biz-data-permission - yudao-spring-boot-starter-biz-error-code yudao-spring-boot-starter-biz-ip yudao-spring-boot-starter-captcha yudao-spring-boot-starter-websocket - yudao-spring-boot-starter-desensitize yudao-framework diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java index 35ebc8ff3..8ffd21ccc 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java @@ -288,11 +288,16 @@ public class CollectionUtils { public static > V getSumValue(List from, Function valueFunc, BinaryOperator accumulator) { + return getSumValue(from, valueFunc, accumulator, null); + } + + public static > V getSumValue(Collection from, Function valueFunc, + BinaryOperator accumulator, V defaultValue) { if (CollUtil.isEmpty(from)) { - return null; + return defaultValue; } - assert from.size() > 0; // 断言,避免告警 - return from.stream().map(valueFunc).reduce(accumulator).get(); + assert !from.isEmpty(); // 断言,避免告警 + return from.stream().map(valueFunc).filter(Objects::nonNull).reduce(accumulator).orElse(defaultValue); } public static void addIfNotNull(Collection coll, T item) { @@ -302,8 +307,12 @@ public class CollectionUtils { coll.add(item); } - public static Collection singleton(T deptId) { - return deptId == null ? Collections.emptyList() : Collections.singleton(deptId); + public static Collection singleton(T obj) { + return obj == null ? Collections.emptyList() : Collections.singleton(obj); + } + + public static List newArrayList(List> list) { + return list.stream().flatMap(Collection::stream).collect(Collectors.toList()); } } diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java index e0b739920..90888d7d3 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java @@ -13,6 +13,16 @@ import java.math.RoundingMode; */ public class MoneyUtils { + /** + * 金额的小数位数 + */ + private static final int PRICE_SCALE = 2; + + /** + * 百分比对应的 BigDecimal 对象 + */ + public static final BigDecimal PERCENT_100 = BigDecimal.valueOf(100); + /** * 计算百分比金额,四舍五入 * @@ -35,6 +45,22 @@ public class MoneyUtils { return calculateRatePrice(price, rate, 0, RoundingMode.FLOOR).intValue(); } + /** + * 计算百分比金额 + * + * @param price 金额(单位分) + * @param count 数量 + * @param percent 折扣(单位分),列如 60.2%,则传入 6020 + * @return 商品总价 + */ + public static Integer calculator(Integer price, Integer count, Integer percent) { + price = price * count; + if (percent == null) { + return price; + } + return MoneyUtils.calculateRatePriceFloor(price, (double) (percent / 100)); + } + /** * 计算百分比金额 * @@ -70,4 +96,36 @@ public class MoneyUtils { return new Money(0, fen).toString(); } + /** + * 金额相乘,默认进行四舍五入 + * + * 位数:{@link #PRICE_SCALE} + * + * @param price 金额 + * @param count 数量 + * @return 金额相乘结果 + */ + public static BigDecimal priceMultiply(BigDecimal price, BigDecimal count) { + if (price == null || count == null) { + return null; + } + return price.multiply(count).setScale(PRICE_SCALE, RoundingMode.HALF_UP); + } + + /** + * 金额相乘(百分比),默认进行四舍五入 + * + * 位数:{@link #PRICE_SCALE} + * + * @param price 金额 + * @param percent 百分比 + * @return 金额相乘结果 + */ + public static BigDecimal priceMultiplyPercent(BigDecimal price, BigDecimal percent) { + if (price == null || percent == null) { + return null; + } + return price.multiply(percent).divide(PERCENT_100, PRICE_SCALE, RoundingMode.HALF_UP); + } + } diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/NumberUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/NumberUtils.java index 55ab367a3..ea131e86e 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/NumberUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/NumberUtils.java @@ -1,7 +1,10 @@ package cn.iocoder.yudao.framework.common.util.number; +import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.StrUtil; +import java.math.BigDecimal; + /** * 数字的工具类,补全 {@link cn.hutool.core.util.NumberUtil} 的功能 * @@ -37,4 +40,21 @@ public class NumberUtils { return distance; } + /** + * 提供精确的乘法运算 + * + * 和 hutool {@link NumberUtil#mul(BigDecimal...)} 的差别是,如果存在 null,则返回 null + * + * @param values 多个被乘值 + * @return 积 + */ + public static BigDecimal mul(BigDecimal... values) { + for (BigDecimal value : values) { + if (value == null) { + return null; + } + } + return NumberUtil.mul(values); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-banner/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-banner/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index e04c9b42c..000000000 --- a/yudao-framework/yudao-spring-boot-starter-banner/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -cn.iocoder.yudao.framework.banner.config.YudaoBannerAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-error-code/pom.xml deleted file mode 100644 index 06e41c1eb..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-error-code/pom.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - yudao-framework - cn.iocoder.boot - ${revision} - - 4.0.0 - yudao-spring-boot-starter-biz-error-code - jar - - ${project.artifactId} - - 错误码 ErrorCode 的自动配置功能,提供如下功能: - 1. 远程读取:项目启动时,从 system-server 服务,读取数据库中的 ErrorCode 错误码,实现错误码的提示可配置; - 2. 自动更新:管理员在管理后台修数据库中的 ErrorCode 错误码时,项目自动从 system-server 服务加载最新的 ErrorCode 错误码; - 3. 自动写入:项目启动时,将项目本地的错误码写到 system-server 服务中,方便管理员在管理后台编辑; - - https://github.com/YunaiV/ruoyi-vue-pro - - - - cn.iocoder.boot - yudao-common - - - - - org.springframework.boot - spring-boot-starter - - - - - cn.iocoder.boot - yudao-module-system-api - ${revision} - - - - jakarta.validation - jakarta.validation-api - provided - - - - diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index ecd3f7183..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -cn.iocoder.yudao.framework.errorcode.config.YudaoErrorCodeAutoConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-sms/pom.xml deleted file mode 100644 index c0d056c18..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/pom.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - cn.iocoder.boot - yudao-framework - ${revision} - - 4.0.0 - yudao-spring-boot-starter-biz-sms - jar - - ${project.artifactId} - 短信拓展,支持阿里云、腾讯云 - https://github.com/YunaiV/ruoyi-vue-pro - - - - cn.iocoder.boot - yudao-common - - - - - org.springframework.boot - spring-boot-starter - - - - - io.opentracing - opentracing-util - - - - - com.google.guava - guava - true - - - - com.fasterxml.jackson.core - jackson-databind - - - com.fasterxml.jackson.core - jackson-core - - - - jakarta.validation - jakarta.validation-api - - - - - - - com.aliyun - aliyun-java-sdk-core - - - com.aliyun - aliyun-java-sdk-dysmsapi - - - com.tencentcloudapi - tencentcloud-sdk-java-sms - - - - - diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/config/YudaoSmsAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/config/YudaoSmsAutoConfiguration.java deleted file mode 100644 index 9873c80d5..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/config/YudaoSmsAutoConfiguration.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.framework.sms.config; - -import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; -import cn.iocoder.yudao.framework.sms.core.client.impl.SmsClientFactoryImpl; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.context.annotation.Bean; - -/** - * 短信配置类 - * - * @author 芋道源码 - */ -@AutoConfiguration -public class YudaoSmsAutoConfiguration { - - @Bean - public SmsClientFactory smsClientFactory() { - return new SmsClientFactoryImpl(); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java deleted file mode 100644 index b9a226fdb..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java +++ /dev/null @@ -1,50 +0,0 @@ -package cn.iocoder.yudao.framework.sms.core.enums; - -import cn.iocoder.yudao.framework.common.exception.ErrorCode; - -/** - * 短信框架的错误码枚举 - * - * 短信框架,使用 2-001-000-000 段 - * - * @author 芋道源码 - */ -public interface SmsFrameworkErrorCodeConstants { - - ErrorCode SMS_UNKNOWN = new ErrorCode(2_001_000_000, "未知错误,需要解析"); - - // ========== 权限 / 限流等相关 2-001-000-100 ========== - - ErrorCode SMS_PERMISSION_DENY = new ErrorCode(2_001_000_100, "没有发送短信的权限"); - ErrorCode SMS_IP_DENY = new ErrorCode(2_001_000_100, "IP 不允许发送短信"); - - // 阿里云:将短信发送频率限制在正常的业务限流范围内。默认短信验证码:使用同一签名,对同一个手机号验证码,支持 1 条 / 分钟,5 条 / 小时,累计 10 条 / 天。 - ErrorCode SMS_SEND_BUSINESS_LIMIT_CONTROL = new ErrorCode(2_001_000_102, "指定手机的发送限流"); - // 阿里云:已经达到您在控制台设置的短信日发送量限额值。在国内消息设置 > 安全设置,修改发送总量阈值。 - ErrorCode SMS_SEND_DAY_LIMIT_CONTROL = new ErrorCode(2_001_000_103, "每天的发送限流"); - - ErrorCode SMS_SEND_CONTENT_INVALID = new ErrorCode(2_001_000_104, "短信内容有敏感词"); - - // 腾讯云:为避免骚扰用户,营销短信只允许在8点到22点发送。 - ErrorCode SMS_SEND_MARKET_LIMIT_CONTROL = new ErrorCode(2_001_000_105, "营销短信发送时间限制"); - - // ========== 模板相关 2-001-000-200 ========== - ErrorCode SMS_TEMPLATE_INVALID = new ErrorCode(2_001_000_200, "短信模板不合法"); // 包括短信模板不存在 - ErrorCode SMS_TEMPLATE_PARAM_ERROR = new ErrorCode(2_001_000_201, "模板参数不正确"); - - // ========== 签名相关 2-001-000-300 ========== - ErrorCode SMS_SIGN_INVALID = new ErrorCode(2_001_000_300, "短信签名不可用"); - - // ========== 账户相关 2-001-000-400 ========== - ErrorCode SMS_ACCOUNT_MONEY_NOT_ENOUGH = new ErrorCode(2_001_000_400, "账户余额不足"); - ErrorCode SMS_ACCOUNT_INVALID = new ErrorCode(2_001_000_401, "apiKey 不存在"); - - // ========== 其它相关 2-001-000-900 开头 ========== - ErrorCode SMS_API_PARAM_ERROR = new ErrorCode(2_001_000_900, "请求参数缺失"); - ErrorCode SMS_MOBILE_INVALID = new ErrorCode(2_001_000_901, "手机格式不正确"); - ErrorCode SMS_MOBILE_BLACK = new ErrorCode(2_001_000_902, "手机号在黑名单中"); - ErrorCode SMS_APP_ID_INVALID = new ErrorCode(2_001_000_903, "SdkAppId不合法"); - - ErrorCode EXCEPTION = new ErrorCode(2_001_000_999, "调用异常"); - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 7c9b740ca..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -cn.iocoder.yudao.framework.sms.config.YudaoSmsAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/pom.xml b/yudao-framework/yudao-spring-boot-starter-desensitize/pom.xml deleted file mode 100644 index 90d30fa1c..000000000 --- a/yudao-framework/yudao-spring-boot-starter-desensitize/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - 4.0.0 - - yudao-framework - cn.iocoder.boot - ${revision} - - - yudao-spring-boot-starter-desensitize - 脱敏组件:支持 JSON 返回数据时,将邮箱、手机等字段进行脱敏 - - - - cn.iocoder.boot - yudao-common - - - - - com.fasterxml.jackson.core - jackson-annotations - - - com.fasterxml.jackson.core - jackson-databind - - - - diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java index fb576d508..2944ca72c 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.framework.file.core.client; +import cn.iocoder.yudao.framework.file.core.client.s3.FilePresignedUrlRespDTO; + /** * 文件客户端 * @@ -18,11 +20,11 @@ public interface FileClient { * 上传文件 * * @param content 文件流 - * @param path 相对路径 + * @param path 相对路径 * @return 完整路径,即 HTTP 访问地址 * @throws Exception 上传文件时,抛出 Exception 异常 */ - String upload(byte[] content, String path, String type) throws Exception; + String upload(byte[] content, String path, String type) throws Exception; /** * 删除文件 @@ -40,4 +42,14 @@ public interface FileClient { */ byte[] getContent(String path) throws Exception; + /** + * 获得文件预签名地址 + * + * @param path 相对路径 + * @return 文件预签名地址 + */ + default FilePresignedUrlRespDTO getPresignedObjectUrl(String path) throws Exception { + throw new UnsupportedOperationException("不支持的操作"); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/FilePresignedUrlRespDTO.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/FilePresignedUrlRespDTO.java new file mode 100644 index 000000000..6048494ed --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/FilePresignedUrlRespDTO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.framework.file.core.client.s3; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 文件预签名地址 Response DTO + * + * @author owen + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class FilePresignedUrlRespDTO { + + /** + * 文件上传 URL(用于上传) + * + * 例如说: + */ + private String uploadUrl; + + /** + * 文件 URL(用于读取、下载等) + */ + private String url; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java index 49238f8f9..e7b470bad 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java @@ -5,8 +5,10 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; import cn.iocoder.yudao.framework.file.core.client.AbstractFileClient; import io.minio.*; +import io.minio.http.Method; import java.io.ByteArrayInputStream; +import java.util.concurrent.TimeUnit; import static cn.iocoder.yudao.framework.file.core.client.s3.S3FileClientConfig.ENDPOINT_ALIYUN; import static cn.iocoder.yudao.framework.file.core.client.s3.S3FileClientConfig.ENDPOINT_TENCENT; @@ -117,4 +119,16 @@ public class S3FileClient extends AbstractFileClient { return IoUtil.readBytes(response); } + @Override + public FilePresignedUrlRespDTO getPresignedObjectUrl(String path) throws Exception { + String uploadUrl = client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder() + .method(Method.PUT) + .bucket(config.getBucket()) + .object(path) + .expiry(10, TimeUnit.MINUTES) // 过期时间(秒数)取值范围:1 秒 ~ 7 天 + .build() + ); + return new FilePresignedUrlRespDTO(uploadUrl, config.getDomain() + "/" + path); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/BpmnModelConstants.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/BpmnModelConstants.java new file mode 100644 index 000000000..c3cce4272 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/BpmnModelConstants.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.framework.flowable.core.enums; + +/** + * 流程常量信息 + */ +public interface BpmnModelConstants { + + String BPMN_FILE_SUFFIX = ".bpmn"; + + /** + * BPMN 中的命名空间 + * + * 这个东西有可能导致无法切换工作流程的实现 + */ + String NAMESPACE = "http://flowable.org/bpmn"; + + /** + * 自定义属性 dataType + */ + String PROCESS_CUSTOM_DATA_TYPE = "dataType"; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/pom.xml b/yudao-framework/yudao-spring-boot-starter-web/pom.xml index 50d986c06..2ec8017d1 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-web/pom.xml @@ -12,7 +12,7 @@ jar ${project.artifactId} - Web 框架,全局异常、API 日志等 + Web 框架,全局异常、API 日志、脱敏、错误码等 https://github.com/YunaiV/ruoyi-vue-pro @@ -54,6 +54,11 @@ yudao-module-infra-api ${revision} + + cn.iocoder.boot + yudao-module-system-api + ${revision} + @@ -61,6 +66,17 @@ jsoup + + + org.springframework.boot + spring-boot-starter-test + test + + + org.mockito + mockito-inline + test + diff --git a/yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/config/YudaoBannerAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/config/YudaoBannerAutoConfiguration.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/config/YudaoBannerAutoConfiguration.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/config/YudaoBannerAutoConfiguration.java diff --git a/yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java similarity index 91% rename from yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java index 19aaf046c..028ac8d71 100644 --- a/yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java @@ -46,6 +46,10 @@ public class BannerApplicationRunner implements ApplicationRunner { if (isNotPresent("cn.iocoder.yudao.module.trade.framework.web.config.TradeWebConfiguration")) { System.out.println("[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]"); } + // ERP 系统 + if (isNotPresent("cn.iocoder.yudao.module.erp.framework.web.config.ErpWebConfiguration")) { + System.out.println("[ERP 系统 yudao-module-erp - 已禁用][参考 https://doc.iocoder.cn/erp/build/ 开启]"); + } // 支付平台 if (isNotPresent("cn.iocoder.yudao.module.pay.framework.pay.config.PayConfiguration")) { System.out.println("[支付系统 yudao-module-pay - 已禁用][参考 https://doc.iocoder.cn/pay/build/ 开启]"); diff --git a/yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/package-info.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/package-info.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/package-info.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/package-info.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/annotation/DesensitizeBy.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/annotation/DesensitizeBy.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/annotation/DesensitizeBy.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/annotation/DesensitizeBy.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/handler/DesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/handler/DesensitizationHandler.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/handler/DesensitizationHandler.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/handler/DesensitizationHandler.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/serializer/StringDesensitizeSerializer.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/serializer/StringDesensitizeSerializer.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/serializer/StringDesensitizeSerializer.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/serializer/StringDesensitizeSerializer.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/EmailDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/EmailDesensitize.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/EmailDesensitize.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/EmailDesensitize.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/RegexDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/RegexDesensitize.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/RegexDesensitize.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/RegexDesensitize.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/BankCardDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/BankCardDesensitize.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/BankCardDesensitize.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/BankCardDesensitize.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/IdCardDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/IdCardDesensitize.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/IdCardDesensitize.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/IdCardDesensitize.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/MobileDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/MobileDesensitize.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/MobileDesensitize.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/MobileDesensitize.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/PasswordDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/PasswordDesensitize.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/PasswordDesensitize.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/PasswordDesensitize.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/SliderDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/SliderDesensitize.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/SliderDesensitize.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/SliderDesensitize.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/BankCardDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/BankCardDesensitization.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/BankCardDesensitization.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/BankCardDesensitization.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/IdCardDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/IdCardDesensitization.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/IdCardDesensitization.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/IdCardDesensitization.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/MobileDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/MobileDesensitization.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/MobileDesensitization.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/MobileDesensitization.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/PasswordDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/PasswordDesensitization.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/PasswordDesensitization.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/PasswordDesensitization.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/package-info.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/package-info.java similarity index 64% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/package-info.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/package-info.java index d56282535..bfe0187be 100644 --- a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/package-info.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/package-info.java @@ -1,4 +1,4 @@ /** * 脱敏组件:支持 JSON 返回数据时,将邮箱、手机等字段进行脱敏 */ -package cn.iocoder.yudao.framework.desensitize.core; +package cn.iocoder.yudao.framework.desensitize; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/config/ErrorCodeProperties.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/config/ErrorCodeProperties.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/config/ErrorCodeProperties.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/config/ErrorCodeProperties.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/config/YudaoErrorCodeAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/config/YudaoErrorCodeAutoConfiguration.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/config/YudaoErrorCodeAutoConfiguration.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/config/YudaoErrorCodeAutoConfiguration.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoader.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoader.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoader.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoader.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/package-info.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/package-info.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/package-info.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/package-info.java diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java index 303b645a3..c494bfefb 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java @@ -313,7 +313,13 @@ public class GlobalExceptionHandler { return CommonResult.error(NOT_IMPLEMENTED.getCode(), "[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]"); } - // 5. 支付平台 + // 5. ERP 系统 + if (message.contains("erp_")) { + log.error("[ERP 系统 yudao-module-erp - 表结构未导入][参考 https://doc.iocoder.cn/erp/build/ 开启]"); + return CommonResult.error(NOT_IMPLEMENTED.getCode(), + "[ERP 系统 yudao-module-erp - 表结构未导入][参考 https://doc.iocoder.cn/erp/build/ 开启]"); + } + // 6. 支付平台 if (message.contains("pay_")) { log.error("[支付模块 yudao-module-pay - 表结构未导入][参考 https://doc.iocoder.cn/pay/build/ 开启]"); return CommonResult.error(NOT_IMPLEMENTED.getCode(), diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 818e33aa3..36ba94cbb 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -3,3 +3,5 @@ cn.iocoder.yudao.framework.jackson.config.YudaoJacksonAutoConfiguration cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration cn.iocoder.yudao.framework.xss.config.YudaoXssAutoConfiguration +cn.iocoder.yudao.framework.banner.config.YudaoBannerAutoConfiguration +cn.iocoder.yudao.framework.errorcode.config.YudaoErrorCodeAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-banner/src/main/resources/banner.txt b/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/banner.txt similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-banner/src/main/resources/banner.txt rename to yudao-framework/yudao-spring-boot-starter-web/src/main/resources/banner.txt diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/BpmResultListenerApi.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/BpmResultListenerApi.java new file mode 100644 index 000000000..d519ed9ed --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/BpmResultListenerApi.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.bpm.api.listener; + +import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; + +// TODO @芋艿:后续改成支持 RPC +/** + * 业务流程实例的结果发生变化的监听器 Api + * + * @author HUIHUI + */ +public interface BpmResultListenerApi { + + /** + * 监听的流程定义 Key + * + * @return 返回监听的流程定义 Key + */ + String getProcessDefinitionKey(); + + /** + * 处理事件 + * + * @param event 事件 + */ + void onEvent(BpmResultListenerRespDTO event); + +} diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/dto/BpmResultListenerRespDTO.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/dto/BpmResultListenerRespDTO.java new file mode 100644 index 000000000..30721785d --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/dto/BpmResultListenerRespDTO.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.bpm.api.listener.dto; + +import lombok.Data; + +// TODO @芋艿:后续改成支持 RPC +/** + * 业务流程实例的结果 Response DTO + * + * @author HUIHUI + */ +@Data +public class BpmResultListenerRespDTO { + + /** + * 流程实例的编号 + */ + private String id; + /** + * 流程实例的 key + */ + private String processDefinitionKey; + /** + * 流程实例的结果 + */ + private Integer result; + /** + * 流程实例对应的业务标识 + * 例如说,请假 + */ + private String businessKey; + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java new file mode 100644 index 000000000..ec7b67e27 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.task; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyMyPageReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyPageItemRespVO; +import cn.iocoder.yudao.module.bpm.convert.cc.BpmProcessInstanceCopyConvert; +import cn.iocoder.yudao.module.bpm.dal.dataobject.cc.BpmProcessInstanceCopyDO; +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; +import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; +import cn.iocoder.yudao.module.bpm.service.task.cc.BpmProcessInstanceCopyService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.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.validation.Valid; +import java.util.Map; +import java.util.stream.Stream; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "管理后台 - 流程实例抄送") +@RestController +@RequestMapping("/bpm/process-instance/cc") +@Validated +public class BpmProcessInstanceCopyController { + + @Resource + private BpmProcessInstanceCopyService processInstanceCopyService; + @Resource + private BpmProcessInstanceService bpmProcessInstanceService; + + @Resource + private AdminUserApi adminUserApi; + + @Resource + private BpmTaskService bpmTaskService; + + @PostMapping("/create") + @Operation(summary = "抄送流程") + @PreAuthorize("@ss.hasPermission('bpm:process-instance-cc:create')") + public CommonResult createProcessInstanceCopy(@Valid @RequestBody BpmProcessInstanceCopyCreateReqVO createReqVO) { + processInstanceCopyService.createProcessInstanceCopy(getLoginUserId(), createReqVO); + return success(true); + } + + @GetMapping("/my-page") + @Operation(summary = "获得抄送流程分页列表") + @PreAuthorize("@ss.hasPermission('bpm:process-instance-cc:query')") + public CommonResult> getProcessInstanceCopyPage( + @Valid BpmProcessInstanceCopyMyPageReqVO pageReqVO) { + PageResult pageResult = processInstanceCopyService.getMyProcessInstanceCopyPage(getLoginUserId(), pageReqVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(new PageResult<>(pageResult.getTotal())); + } + + // 拼接返回 + Map taskNameMap = bpmTaskService.getTaskNameByTaskIds( + convertSet(pageResult.getList(), BpmProcessInstanceCopyDO::getTaskId)); + Map processNameMap = bpmProcessInstanceService.getProcessInstanceNameMap( + convertSet(pageResult.getList(), BpmProcessInstanceCopyDO::getProcessInstanceId)); + Map userMap = adminUserApi.getUserMap(convertListByFlatMap(pageResult.getList(), + copy -> Stream.of(copy.getStartUserId(), Long.parseLong(copy.getCreator())))); + return success(BpmProcessInstanceCopyConvert.INSTANCE.convertPage(pageResult, taskNameMap, processNameMap, userMap)); + } + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyCreateReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyCreateReqVO.java new file mode 100644 index 000000000..359fa0065 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyCreateReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance; + +import io.swagger.v3.oas.annotations.media.Schema; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Schema(description = "管理后台 - 流程实例抄送的创建 Request VO") +@Data +public class BpmProcessInstanceCopyCreateReqVO { + + @Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotEmpty(message = "任务编号不能为空") + private String taskId; + + @Schema(description = "抄送原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "请帮忙审查下!") + @NotBlank(message = "抄送原因不能为空") + private String reason; + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/listener/BpmServiceResultListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/listener/BpmServiceResultListener.java new file mode 100644 index 000000000..49de046a2 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/listener/BpmServiceResultListener.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.bpm.framework.bpm.listener; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.bpm.api.listener.BpmResultListenerApi; +import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; +import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; + +// TODO @芋艿:后续改成支持 RPC +/** + * 业务流程结果监听器实现类 + * + * @author HUIHUI + */ +@Component +public class BpmServiceResultListener implements ApplicationListener { + + @Resource + private List bpmResultListenerApis; + + @Override + public final void onApplicationEvent(BpmProcessInstanceResultEvent event) { + bpmResultListenerApis.forEach(bpmResultListenerApi -> { + if (!StrUtil.equals(event.getProcessDefinitionKey(), bpmResultListenerApi.getProcessDefinitionKey())) { + return; + } + bpmResultListenerApi.onEvent(BeanUtils.toBean(event, BpmResultListenerRespDTO.class)); + }); + } + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java new file mode 100644 index 000000000..87f3d9aa5 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.module.bpm.framework.flowable.core.handler; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.flowable.core.enums.BpmnModelConstants; +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import lombok.AllArgsConstructor; +import org.flowable.bpmn.model.FlowElement; +import org.flowable.bpmn.model.UserTask; +import org.flowable.engine.delegate.DelegateExecution; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + +// TODO @芋艿:bpmn 分配人融合时,需要搞下这块; +/** + * 多实例处理类 + */ +@AllArgsConstructor +@Component("multiInstanceHandler") +public class MultiInstanceHandler { + + @Resource + private AdminUserApi userApi; + + @Resource + private PermissionApi permissionApi; + + /** + * 流程发起人那种情况不需要处理, + * 由 flowable 完成 + * + * @param execution flowable的执行对象 + * @return 用户ID + */ + public Set getUserIds(DelegateExecution execution) { + Set candidateUserIds = new LinkedHashSet<>(); + FlowElement flowElement = execution.getCurrentFlowElement(); + if (ObjectUtil.isNotEmpty(flowElement) && flowElement instanceof UserTask) { + UserTask userTask = (UserTask) flowElement; + String dataType = userTask.getAttributeValue(BpmnModelConstants.NAMESPACE, BpmnModelConstants.PROCESS_CUSTOM_DATA_TYPE); + if ("USERS".equals(dataType) && CollUtil.isNotEmpty(userTask.getCandidateUsers())) { + // 添加候选用户id + candidateUserIds.addAll(userTask.getCandidateUsers()); + } else if (CollUtil.isNotEmpty(userTask.getCandidateGroups())) { + // 获取组的ID,角色ID集合或部门ID集合 + List groups = userTask.getCandidateGroups().stream() + // 例如部门DEPT100,100才是部门id + .map(item -> Long.parseLong(item.substring(4))) + .collect(Collectors.toList()); + List userIds = new ArrayList<>(); + if ("ROLES".equals(dataType)) { + // 通过角色id,获取所有用户id集合 + Set userRoleIdListByRoleIds = permissionApi.getUserRoleIdListByRoleIds(groups); + userIds = new ArrayList<>(userRoleIdListByRoleIds); + } else if ("DEPTS".equals(dataType)) { + // 通过部门id,获取所有用户id集合 + List userListByDeptIds = userApi.getUserListByDeptIds(groups); + userIds = convertList(userListByDeptIds, AdminUserRespDTO::getId); + } + // 添加候选用户id + userIds.forEach(id -> candidateUserIds.add(String.valueOf(id))); + } + } + return candidateUserIds; + } + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyService.java new file mode 100644 index 000000000..208749a57 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyService.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.bpm.service.task.cc; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyMyPageReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.cc.BpmProcessInstanceCopyDO; +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; + +/** + * 流程抄送 Service 接口 + * + * 现在是在审批的时候进行流程抄送 + */ +public interface BpmProcessInstanceCopyService { + + // TODO 芋艿:这块要 review 下;思考下~~ + /** + * 抄送 + * @param sourceInfo 抄送源信息,方便抄送处理 + * @return + */ + boolean makeCopy(BpmCandidateSourceInfo sourceInfo); + + /** + * 流程实例的抄送 + * + * @param userId 当前登录用户 + * @param createReqVO 创建的抄送请求 + */ + void createProcessInstanceCopy(Long userId, BpmProcessInstanceCopyCreateReqVO createReqVO); + + /** + * 抄送的流程的分页 + * @param userId 当前登录用户 + * @param pageReqVO 分页请求 + * @return 抄送的分页结果 + */ + PageResult getMyProcessInstanceCopyPage(Long userId, + BpmProcessInstanceCopyMyPageReqVO pageReqVO); +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java new file mode 100644 index 000000000..d53319633 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java @@ -0,0 +1,140 @@ +package cn.iocoder.yudao.module.bpm.service.task.cc; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyMyPageReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.cc.BpmProcessInstanceCopyDO; +import cn.iocoder.yudao.module.bpm.dal.mysql.cc.BpmProcessInstanceCopyMapper; +import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants; +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessorChain; +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; +import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; +import cn.iocoder.yudao.module.bpm.service.task.cc.dto.BpmDelegateExecutionDTO; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; + +/** + * 流程抄送 Service 实现类 + * + * @author kyle + */ +@Service +@Validated +@Slf4j +public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopyService { + + @Resource + private BpmProcessInstanceCopyMapper processInstanceCopyMapper; + + @Resource + private RuntimeService runtimeService; + + @Resource + private BpmCandidateSourceInfoProcessorChain processorChain; + + @Resource + @Lazy + private BpmTaskService bpmTaskService; + @Resource + @Lazy + private BpmProcessInstanceService bpmProcessInstanceService; + + @Override + public boolean makeCopy(BpmCandidateSourceInfo sourceInfo) { + if (null == sourceInfo) { + return false; + } + + Task task = bpmTaskService.getTask(sourceInfo.getTaskId()); + if (ObjectUtil.isNull(task)) { + return false; + } + String processInstanceId = task.getProcessInstanceId(); + if (StrUtil.isBlank(processInstanceId)) { + return false; + } + DelegateExecution executionEntity = new BpmDelegateExecutionDTO(processInstanceId); + Set ccCandidates = processorChain.calculateTaskCandidateUsers(executionEntity, sourceInfo); + if (CollUtil.isEmpty(ccCandidates)) { + log.warn("相关抄送人不存在 {}", sourceInfo.getTaskId()); + return false; + } else { + BpmProcessInstanceCopyDO copyDO = new BpmProcessInstanceCopyDO(); + // 调用 + // 设置任务id + copyDO.setTaskId(sourceInfo.getTaskId()); + copyDO.setTaskName(task.getName()); + copyDO.setProcessInstanceId(processInstanceId); + ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() + .processInstanceId(processInstanceId) + .singleResult(); + if (null == processInstance) { + log.warn("相关流程实例不存在 {}", sourceInfo.getTaskId()); + return false; + } + copyDO.setStartUserId(Long.parseLong(processInstance.getStartUserId())); + copyDO.setProcessInstanceName(processInstance.getName()); + copyDO.setCategory(null); // TODO 芋艿:貌似新版本,没 processInstance.getProcessDefinitionCategory() 字段? + copyDO.setReason(sourceInfo.getReason()); + copyDO.setCreator(sourceInfo.getCreator()); + copyDO.setCreateTime(LocalDateTime.now()); + List copyList = new ArrayList<>(ccCandidates.size()); + for (Long userId : ccCandidates) { + BpmProcessInstanceCopyDO copy = BeanUtil.copyProperties(copyDO, BpmProcessInstanceCopyDO.class); + copy.setUserId(userId); + copyList.add(copy); + } + return processInstanceCopyMapper.insertBatch(copyList); + } + } + + @Override + public void createProcessInstanceCopy(Long userId, BpmProcessInstanceCopyCreateReqVO reqVO) { + // 1.1 校验任务存在 + Task task = bpmTaskService.getTask(reqVO.getTaskId()); + if (ObjectUtil.isNull(task)) { + throw exception(ErrorCodeConstants.TASK_NOT_EXISTS); + } + // 1.2 校验流程存在 + String processInstanceId = task.getProcessInstanceId(); + ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(processInstanceId); + if (processInstance == null) { + log.warn("[createProcessInstanceCopy][任务({}) 对应的流程不存在]", reqVO.getTaskId()); + throw exception(ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS); + } + + // 2. 创建抄送流程 + BpmProcessInstanceCopyDO copy = new BpmProcessInstanceCopyDO() + .setTaskId(reqVO.getTaskId()).setTaskName(task.getName()) + .setProcessInstanceId(processInstanceId).setStartUserId(Long.valueOf(processInstance.getStartUserId())) + .setProcessInstanceName(processInstance.getName()) + .setCategory(null) // TODO 芋艿:貌似新版本,没 processInstance.getProcessDefinitionCategory() 字段? + .setReason(reqVO.getReason()); + processInstanceCopyMapper.insert(copy); + } + + @Override + public PageResult getMyProcessInstanceCopyPage(Long userId, BpmProcessInstanceCopyMyPageReqVO pageReqVO) { + return processInstanceCopyMapper.selectPage(userId, pageReqVO); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.http b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.http new file mode 100644 index 000000000..b9e9a4edf --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.http @@ -0,0 +1,9 @@ +### 合同金额排行榜 +GET {{baseUrl}}/crm/bi-rank/get-contract-price-rank?deptId=100×[0]=2022-12-12 00:00:00×[1]=2024-12-12 23:59:59 +Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} + +### 回款金额排行榜 +GET {{baseUrl}}/crm/bi-rank/get-receivable-price-rank?deptId=100×[0]=2022-12-12 00:00:00×[1]=2024-12-12 23:59:59 +Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} \ 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/bi/CrmBiRankController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.java new file mode 100644 index 000000000..ee7c506f0 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.java @@ -0,0 +1,87 @@ +package cn.iocoder.yudao.module.crm.controller.admin.bi; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRanKRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRankReqVO; +import cn.iocoder.yudao.module.crm.service.bi.CrmBiRankingService; +import io.swagger.v3.oas.annotations.Operation; +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.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + + +@Tag(name = "管理后台 - CRM BI 排行榜") +@RestController +@RequestMapping("/crm/bi-rank") +@Validated +public class CrmBiRankController { + + @Resource + private CrmBiRankingService rankingService; + + @GetMapping("/get-contract-price-rank") + @Operation(summary = "获得合同金额排行榜") + @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") + public CommonResult> getContractPriceRank(@Valid CrmBiRankReqVO rankingReqVO) { + return success(rankingService.getContractPriceRank(rankingReqVO)); + } + + @GetMapping("/get-receivable-price-rank") + @Operation(summary = "获得回款金额排行榜") + @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") + public CommonResult> getReceivablePriceRank(@Valid CrmBiRankReqVO rankingReqVO) { + return success(rankingService.getReceivablePriceRank(rankingReqVO)); + } + + @GetMapping("/get-contract-count-rank") + @Operation(summary = "获得签约合同数量排行榜") + @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") + public CommonResult> getContractCountRank(@Valid CrmBiRankReqVO rankingReqVO) { + return success(rankingService.getContractCountRank(rankingReqVO)); + } + + @GetMapping("/get-product-sales-rank") + @Operation(summary = "获得产品销量排行榜") + @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") + public CommonResult> getProductSalesRank(@Valid CrmBiRankReqVO rankingReqVO) { + return success(rankingService.getProductSalesRank(rankingReqVO)); + } + + @GetMapping("/get-customer-count-rank") + @Operation(summary = "获得新增客户数排行榜") + @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") + public CommonResult> getCustomerCountRank(@Valid CrmBiRankReqVO rankingReqVO) { + return success(rankingService.getCustomerCountRank(rankingReqVO)); + } + + @GetMapping("/get-contacts-count-rank") + @Operation(summary = "获得新增联系人数排行榜") + @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") + public CommonResult> getContactsCountRank(@Valid CrmBiRankReqVO rankingReqVO) { + return success(rankingService.getContactsCountRank(rankingReqVO)); + } + + @GetMapping("/get-follow-count-rank") + @Operation(summary = "获得跟进次数排行榜") + @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") + public CommonResult> getFollowCountRank(@Valid CrmBiRankReqVO rankingReqVO) { + return success(rankingService.getFollowCountRank(rankingReqVO)); + } + + @GetMapping("/get-follow-customer-count-rank") + @Operation(summary = "获得跟进客户数排行榜") + @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") + public CommonResult> getFollowCustomerCountRank(@Valid CrmBiRankReqVO rankingReqVO) { + return success(rankingService.getFollowCustomerCountRank(rankingReqVO)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRanKRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRanKRespVO.java new file mode 100644 index 000000000..404ee3352 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRanKRespVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.crm.controller.admin.bi.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + + +@Schema(description = "管理后台 - CRM BI 排行榜 Response VO") +@Data +public class CrmBiRanKRespVO { + + @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long ownerUserId; + + @Schema(description = "姓名", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private String nickname; + + @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private String deptName; + + /** + * 数量是个特别“抽象”的概念,在不同排行下,代表不同含义 + * + * 1. 金额:合同金额排行、回款金额排行 + * 2. 个数:签约合同排行、产品销量排行、产品销量排行、新增客户数排行、新增联系人排行、跟进次数排行、跟进客户数排行 + */ + @Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer count; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRankReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRankReqVO.java new file mode 100644 index 000000000..3f3fdc5fb --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRankReqVO.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.crm.controller.admin.bi.vo; + +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 java.util.List; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - CRM BI 排行榜 Request VO") +@Data +public class CrmBiRankReqVO { + + @Schema(description = "部门 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "部门 id 不能为空") + private Long deptId; + + /** + * userIds 目前不用前端传递,目前是方便后端通过 deptId 读取编号后,设置回来 + * + * 后续,可能会支持选择部分用户进行查询 + */ + @Schema(description = "负责人用户 id 集合", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "2") + private List userIds; + + @Schema(description = "时间范围", requiredMode = Schema.RequiredMode.REQUIRED) + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @NotEmpty(message = "时间范围不能为空") + private LocalDateTime[] times; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportExcelVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportExcelVO.java new file mode 100644 index 000000000..4f57564dd --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportExcelVO.java @@ -0,0 +1,71 @@ +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 com.alibaba.excel.annotation.ExcelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.*; + +/** + * 客户 Excel 导入 VO + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = false) // 设置 chain = false,避免用户导入有问题 +public class CrmCustomerImportExcelVO { + + @ExcelProperty("客户名称") + private String name; + + // TODO @puhui999:industryId、level、source 字段,可以研究下怎么搞下拉框 + @ExcelProperty(value = "所属行业", converter = DictConvert.class) + @DictFormat(CRM_CUSTOMER_INDUSTRY) + private Integer industryId; + + @ExcelProperty(value = "客户等级", converter = DictConvert.class) + @DictFormat(CRM_CUSTOMER_LEVEL) + private Integer level; + + @ExcelProperty(value = "客户来源", converter = DictConvert.class) + @DictFormat(CRM_CUSTOMER_SOURCE) + private Integer source; + + @ExcelProperty("手机") + private String mobile; + + @ExcelProperty("电话") + private String telephone; + + @ExcelProperty("网址") + private String website; + + @ExcelProperty("QQ") + private String qq; + + @ExcelProperty("微信") + private String wechat; + + @ExcelProperty("邮箱") + private String email; + + @ExcelProperty("客户描述") + private String description; + + @ExcelProperty("备注") + private String remark; + + // TODO @puhui999:需要选择省市区,需要研究下,怎么搞合理点; + @ExcelProperty("地区编号") + private Integer areaId; + + @ExcelProperty("详细地址") + private String detailAddress; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportReqVO.java new file mode 100644 index 000000000..85e8d2df4 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportReqVO.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 客户导入 Request VO") +@Data +@Builder +public class CrmCustomerImportReqVO { + + @Schema(description = "Excel 文件", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "Excel 文件不能为空") + private MultipartFile file; + + @Schema(description = "是否支持更新", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否支持更新不能为空") + private Boolean updateSupport; + + @Schema(description = "负责人", example = "1") + private Long ownerUserId; // 为 null 则客户进入公海 + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportRespVO.java new file mode 100644 index 000000000..de35b7b92 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportRespVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +@Schema(description = "管理后台 - 客户导入 Response VO") +@Data +@Builder +public class CrmCustomerImportRespVO { + + @Schema(description = "创建成功的客户名数组", requiredMode = Schema.RequiredMode.REQUIRED) + private List createCustomerNames; + + @Schema(description = "更新成功的客户名数组", requiredMode = Schema.RequiredMode.REQUIRED) + private List updateCustomerNames; + + @Schema(description = "导入失败的客户集合,key 为客户名,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED) + private Map failureCustomerNames; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java new file mode 100644 index 000000000..c541c1c0e --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.crm.controller.admin.operatelog; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo.CrmOperateLogPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo.CrmOperateLogV2RespVO; +import cn.iocoder.yudao.module.crm.enums.LogRecordConstants; +import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; +import io.swagger.v3.oas.annotations.Operation; +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.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.HashMap; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; + +@Tag(name = "管理后台 - CRM 操作日志") +@RestController +@RequestMapping("/crm/operate-log") +@Validated +public class CrmOperateLogController { + + @Resource + private OperateLogApi operateLogApi; + + /** + * {@link CrmBizTypeEnum} 与 {@link LogRecordConstants} 的映射关系 + */ + private static final Map BIZ_TYPE_MAP = new HashMap<>(); + + static { + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_LEADS.getType(), CRM_LEADS_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_CUSTOMER.getType(), CRM_CUSTOMER_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_CONTACT.getType(), CRM_CONTACT_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_BUSINESS.getType(), CRM_BUSINESS_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_CONTRACT.getType(), CRM_CONTRACT_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_PRODUCT.getType(), CRM_PRODUCT_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_RECEIVABLE.getType(), CRM_RECEIVABLE_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), CRM_RECEIVABLE_PLAN_TYPE); + } + + @GetMapping("/page") + @Operation(summary = "获得操作日志") + @PreAuthorize("@ss.hasPermission('crm:operate-log:query')") + public CommonResult> getCustomerOperateLog(@Valid CrmOperateLogPageReqVO pageReqVO) { + OperateLogV2PageReqDTO reqDTO = new OperateLogV2PageReqDTO(); + reqDTO.setPageSize(PAGE_SIZE_NONE); // 默认不分页,需要分页需注释 + reqDTO.setBizType(BIZ_TYPE_MAP.get(pageReqVO.getBizType())).setBizId(pageReqVO.getBizId()); + return success(BeanUtils.toBean(operateLogApi.getOperateLogPage(reqDTO), CrmOperateLogV2RespVO.class)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogPageReqVO.java new file mode 100644 index 000000000..7bed826ae --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogPageReqVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; +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 CrmOperateLogPageReqVO extends PageParam { + + @Schema(description = "数据类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @InEnum(CrmBizTypeEnum.class) + @NotNull(message = "数据类型不能为空") + private Integer bizType; + + @Schema(description = "数据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "数据编号不能为空") + private Long bizId; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogV2RespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogV2RespVO.java new file mode 100644 index 000000000..b3405428f --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogV2RespVO.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - CRM 跟进 Response VO") +@Data +@ExcelIgnoreUnannotated +public class CrmOperateLogV2RespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private Long id; + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long userId; + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + private String userName; + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer userType; + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private String type; + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "修改客户") + private String subType; + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private Long bizId; + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "将什么从什么改为了什么") + private String action; + + @Schema(description = "编号", example = "{orderId: 1}") + private String extra; + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-01-01") + private LocalDateTime createTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java new file mode 100644 index 000000000..bc977c78f --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.module.crm.dal.dataobject.contract; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 合同产品关联表 DO + * + * @author HUIHUI + */ +@TableName("crm_contract_product") +@KeySequence("crm_contract_product_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CrmContractProductDO extends BaseDO { + + /** + * 主键 + */ + @TableId + private Long id; + /** + * 产品编号 + * + * 关联 {@link CrmProductDO#getId()} + */ + private Long productId; + /** + * 合同编号 + * + * 关联 {@link CrmContractDO#getId()} + */ + private Long contractId; + /** + * 产品单价 + */ + private Integer price; + /** + * 销售价格, 单位:分 + */ + private Integer salesPrice; + /** + * 数量 + */ + private Integer count; + /** + * 折扣 + */ + private Integer discountPercent; + /** + * 总计价格(折扣后价格) + * + * TODO @puhui999:可以写下计算公式哈; + */ + private Integer totalPrice; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java new file mode 100644 index 000000000..9b71df7b6 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java @@ -0,0 +1,81 @@ +package cn.iocoder.yudao.module.crm.dal.mysql.bi; + +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRanKRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRankReqVO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * CRM BI 排行榜 Mapper + * + * @author anhaohao + */ +@Mapper +public interface CrmBiRankingMapper { + + /** + * 查询合同金额排行榜 + * + * @param rankReqVO 参数 + * @return 合同金额排行榜 + */ + List selectContractPriceRank(CrmBiRankReqVO rankReqVO); + + /** + * 查询回款金额排行榜 + * + * @param rankReqVO 参数 + * @return 回款金额排行榜 + */ + List selectReceivablePriceRank(CrmBiRankReqVO rankReqVO); + + /** + * 查询签约合同数量排行榜 + * + * @param rankReqVO 参数 + * @return 签约合同数量排行榜 + */ + List selectContractCountRank(CrmBiRankReqVO rankReqVO); + + /** + * 查询产品销量排行榜 + * + * @param rankReqVO 参数 + * @return 产品销量排行榜 + */ + List selectProductSalesRank(CrmBiRankReqVO rankReqVO); + + /** + * 查询新增客户数排行榜 + * + * @param rankReqVO 参数 + * @return 新增客户数排行榜 + */ + List selectCustomerCountRank(CrmBiRankReqVO rankReqVO); + + /** + * 查询联系人数量排行榜 + * + * @param rankReqVO 参数 + * @return 联系人数量排行榜 + */ + List selectContactsCountRank(CrmBiRankReqVO rankReqVO); + + /** + * 查询跟进次数排行榜 + * + * @param rankReqVO 参数 + * @return 跟进次数排行榜 + */ + List selectFollowCountRank(CrmBiRankReqVO rankReqVO); + + /** + * 查询跟进客户数排行榜 + * + * @param rankReqVO 参数 + * @return 跟进客户数排行榜 + */ + List selectFollowCustomerCountRank(CrmBiRankReqVO rankReqVO); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractProductMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractProductMapper.java new file mode 100644 index 000000000..814024125 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractProductMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.crm.dal.mysql.contract; + + +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.contract.CrmContractProductDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 合同产品 Mapper + * + * @author HUIHUI + */ +@Mapper +public interface CrmContractProductMapper extends BaseMapperX { + + // TODO @puhui999:用不到的方法,看看是不是删除哈 + default void deleteByContractId(Long contractId) { // TODO @lzxhqs:第一个方法,和类之间最好空一行; + delete(CrmContractProductDO::getContractId, contractId); + } + + default CrmContractProductDO selectByContractId(Long contractId) { + return selectOne(CrmContractProductDO::getContractId, contractId); + } + + default List selectListByContractId(Long contractId) { + return selectList(new LambdaQueryWrapperX().eq(CrmContractProductDO::getContractId, contractId)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/customer/CrmCustomerAutoPutPoolJob.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/customer/CrmCustomerAutoPutPoolJob.java new file mode 100644 index 000000000..06f8d745b --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/customer/CrmCustomerAutoPutPoolJob.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.crm.job.customer; + +import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; +import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; +import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 客户自动掉入公海 Job + * + * @author 芋道源码 + */ +@Component +public class CrmCustomerAutoPutPoolJob implements JobHandler { + + @Resource + private CrmCustomerService customerService; + + @Override + @TenantJob + public String execute(String param) { + int count = customerService.autoPutCustomerPool(); + return String.format("掉入公海客户 %s 个", count); + } + +} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/package-info.java new file mode 100644 index 000000000..144f64d02 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/package-info.java @@ -0,0 +1,4 @@ +/** + * TODO 芋艿:临时占位,后续可删除 + */ +package cn.iocoder.yudao.module.crm.job; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingService.java new file mode 100644 index 000000000..2ff28d385 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingService.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.crm.service.bi; + + +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRanKRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRankReqVO; + +import java.util.List; + +/** + * CRM BI 排行榜 Service 接口 + * + * @author anhaohao + */ +public interface CrmBiRankingService { + + /** + * 获得合同金额排行榜 + * + * @param rankReqVO 排行参数 + * @return 合同金额排行榜 + */ + List getContractPriceRank(CrmBiRankReqVO rankReqVO); + + /** + * 获得回款金额排行榜 + * + * @param rankReqVO 排行参数 + * @return 回款金额排行榜 + */ + List getReceivablePriceRank(CrmBiRankReqVO rankReqVO); + + /** + * 获得签约合同数量排行榜 + * + * @param rankReqVO 排行参数 + * @return 签约合同数量排行榜 + */ + List getContractCountRank(CrmBiRankReqVO rankReqVO); + + /** + * 获得产品销量排行榜 + * + * @param rankReqVO 排行参数 + * @return 产品销量排行榜 + */ + List getProductSalesRank(CrmBiRankReqVO rankReqVO); + + /** + * 获得新增客户数排行榜 + * + * @param rankReqVO 排行参数 + * @return 新增客户数排行榜 + */ + List getCustomerCountRank(CrmBiRankReqVO rankReqVO); + + /** + * 获得联系人数量排行榜 + * + * @param rankReqVO 排行参数 + * @return 联系人数量排行榜 + */ + List getContactsCountRank(CrmBiRankReqVO rankReqVO); + + /** + * 获得跟进次数排行榜 + * + * @param rankReqVO 排行参数 + * @return 跟进次数排行榜 + */ + List getFollowCountRank(CrmBiRankReqVO rankReqVO); + + /** + * 获得跟进客户数排行榜 + * + * @param rankReqVO 排行参数 + * @return 跟进客户数排行榜 + */ + List getFollowCustomerCountRank(CrmBiRankReqVO rankReqVO); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingServiceImpl.java new file mode 100644 index 000000000..a365c6028 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingServiceImpl.java @@ -0,0 +1,134 @@ +package cn.iocoder.yudao.module.crm.service.bi; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRanKRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRankReqVO; +import cn.iocoder.yudao.module.crm.dal.mysql.bi.CrmBiRankingMapper; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +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.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +/** + * CRM BI 排行榜 Service 实现类 + * + * @author anhaohao + */ +@Service +@Validated +public class CrmBiRankingServiceImpl implements CrmBiRankingService { + + @Resource + private CrmBiRankingMapper biRankingMapper; + + @Resource + private AdminUserApi adminUserApi; + @Resource + private DeptApi deptApi; + + @Override + public List getContractPriceRank(CrmBiRankReqVO rankReqVO) { + return getRank(rankReqVO, biRankingMapper::selectContractPriceRank); + } + + @Override + public List getReceivablePriceRank(CrmBiRankReqVO rankReqVO) { + return getRank(rankReqVO, biRankingMapper::selectReceivablePriceRank); + } + + @Override + public List getContractCountRank(CrmBiRankReqVO rankReqVO) { + return getRank(rankReqVO, biRankingMapper::selectContractCountRank); + } + + @Override + public List getProductSalesRank(CrmBiRankReqVO rankReqVO) { + return getRank(rankReqVO, biRankingMapper::selectProductSalesRank); + } + + @Override + public List getCustomerCountRank(CrmBiRankReqVO rankReqVO) { + return getRank(rankReqVO, biRankingMapper::selectCustomerCountRank); + } + + @Override + public List getContactsCountRank(CrmBiRankReqVO rankReqVO) { + return getRank(rankReqVO, biRankingMapper::selectContactsCountRank); + } + + @Override + public List getFollowCountRank(CrmBiRankReqVO rankReqVO) { + return getRank(rankReqVO, biRankingMapper::selectFollowCountRank); + } + + @Override + public List getFollowCustomerCountRank(CrmBiRankReqVO rankReqVO) { + return getRank(rankReqVO, biRankingMapper::selectFollowCustomerCountRank); + } + + /** + * 获得排行版数据 + * + * @param rankReqVO 参数 + * @param rankFunction 排行榜方法 + * @return 排行版数据 + */ + private List getRank(CrmBiRankReqVO rankReqVO, Function> rankFunction) { + // 1. 获得用户编号数组 + rankReqVO.setUserIds(getUserIds(rankReqVO.getDeptId())); + if (CollUtil.isEmpty(rankReqVO.getUserIds())) { + return Collections.emptyList(); + } + // 2. 获得排行数据 + List ranks = rankFunction.apply(rankReqVO); + if (CollUtil.isEmpty(ranks)) { + return Collections.emptyList(); + } + ranks.sort(Comparator.comparing(CrmBiRanKRespVO::getCount).reversed()); + // 3. 拼接用户信息 + appendUserInfo(ranks); + return ranks; + } + + /** + * 拼接用户信息(昵称、部门) + * + * @param ranks 排行榜数据 + */ + private void appendUserInfo(List ranks) { + Map userMap = adminUserApi.getUserMap(convertSet(ranks, CrmBiRanKRespVO::getOwnerUserId)); + Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); + ranks.forEach(rank -> MapUtils.findAndThen(userMap, rank.getOwnerUserId(), user -> { + rank.setNickname(user.getNickname()); + MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> rank.setDeptName(dept.getName())); + })); + } + + /** + * 获得部门下的用户编号数组,包括子部门的 + * + * @param deptId 部门编号 + * @return 用户编号数组 + */ + public List getUserIds(Long deptId) { + // 1. 获得部门列表 + List deptIds = convertList(deptApi.getChildDeptList(deptId), DeptRespDTO::getId); + deptIds.add(deptId); + // 2. 获得用户编号 + return convertList(adminUserApi.getUserListByDeptIds(deptIds), AdminUserRespDTO::getId); + } + +} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java new file mode 100644 index 000000000..a9f0f8bc7 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.crm.service.business.bo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * 更新商机商品 Update Req BO + * + * @author HUIHUI + */ +@Data +public class CrmBusinessUpdateProductReqBO { + + /** + * 商机编号 + */ + @NotNull(message = "商机编号不能为空") + private Long id; + + // TODO @芋艿:再想想 + @NotEmpty(message = "产品列表不能为空") + private List productItems; + + @Schema(description = "产品列表") + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class CrmBusinessProductItem { + + @Schema(description = "产品编号", example = "20529") + @NotNull(message = "产品编号不能为空") + private Long id; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") + @NotNull(message = "产品数量不能为空") + private Integer count; + + @Schema(description = "产品折扣") + private Integer discountPercent; + + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java new file mode 100644 index 000000000..8f374ee7f --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.crm.service.contract.listener; + +import cn.iocoder.yudao.module.bpm.api.listener.BpmResultListenerApi; +import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; +import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; +import cn.iocoder.yudao.module.crm.service.contract.CrmContractServiceImpl; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +// TODO @芋艿:后续改成支持 RPC +/** + * 合同审批的结果的监听器实现类 + * + * @author HUIHUI + */ +@Component +public class CrmContractResultListener implements BpmResultListenerApi { + + @Resource + private CrmContractService contractService; + + @Override + public String getProcessDefinitionKey() { + return CrmContractServiceImpl.CONTRACT_APPROVE; + } + + @Override + public void onEvent(BpmResultListenerRespDTO event) { + contractService.updateContractAuditStatus(event); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java new file mode 100644 index 000000000..7a1b35ca9 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java @@ -0,0 +1,125 @@ +package cn.iocoder.yudao.module.crm.service.customer.bo; + +import cn.iocoder.yudao.framework.common.validation.Mobile; +import cn.iocoder.yudao.framework.common.validation.Telephone; +import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 客户创建 Create Req BO + * + * @author HUIHUI + */ +@Data +public class CrmCustomerCreateReqBO { + + /** + * 客户名称 + */ + @NotEmpty(message = "客户名称不能为空") + private String name; + /** + * 跟进状态 + */ + private Boolean followUpStatus; + /** + * 锁定状态 + */ + private Boolean lockStatus; + /** + * 成交状态 + */ + private Boolean dealStatus; + /** + * 所属行业 + * + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_INDUSTRY} + */ + private Integer industryId; + /** + * 客户等级 + * + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_LEVEL} + */ + private Integer level; + /** + * 客户来源 + * + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_SOURCE} + */ + private Integer source; + + /** + * 手机 + */ + @Mobile + private String mobile; + /** + * 电话 + */ + @Telephone + private String telephone; + /** + * 网址 + */ + private String website; + /** + * QQ + */ + private String qq; + /** + * wechat + */ + private String wechat; + + /** + * 邮箱 + */ + @Email(message = "邮箱格式不正确") + private String email; + + /** + * 客户描述 + */ + @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符") + private String description; + /** + * 备注 + */ + private String remark; + /** + * 负责人的用户编号 + * + * 关联 AdminUserDO 的 id 字段 + */ + private Long ownerUserId; + /** + * 所在地 + * + * 关联 {@link cn.iocoder.yudao.framework.ip.core.Area#getId()} 字段 + */ + private Integer areaId; + /** + * 详细地址 + */ + private String detailAddress; + + /** + * 最后跟进时间 + */ + private LocalDateTime contactLastTime; + /** + * 最后跟进内容 + */ + private String contactLastContent; + /** + * 下次联系时间 + */ + private LocalDateTime contactNextTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java new file mode 100644 index 000000000..280bcad61 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java @@ -0,0 +1,78 @@ +package cn.iocoder.yudao.module.crm.service.followup.bo; + +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; +import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; +import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 跟进信息 Create Req BO + * + * @author HUIHUI + */ +@Data +public class CrmFollowUpCreateReqBO { + + /** + * 数据类型 + * + * 枚举 {@link CrmBizTypeEnum} + */ + @NotNull(message = "数据类型不能为空") + private Integer bizType; + /** + * 数据编号 + * + * 关联 {@link CrmBizTypeEnum} 对应模块 DO 的 id 字段 + */ + @NotNull(message = "数据编号不能为空") + private Long bizId; + + /** + * 跟进类型 + * + * 关联 {@link DictTypeConstants#CRM_FOLLOW_UP_TYPE} 字典 + */ + @NotNull(message = "跟进类型不能为空") + private Integer type; + /** + * 跟进内容 + */ + @NotEmpty(message = "跟进内容不能为空") + private String content; + /** + * 下次联系时间 + */ + @NotNull(message = "下次联系时间不能为空") + private LocalDateTime nextTime; + + /** + * 图片 + */ + private List picUrls; + /** + * 附件 + */ + private List fileUrls; + + /** + * 关联的商机编号数组 + * + * 关联 {@link CrmBusinessDO#getId()} + */ + private List businessIds; + + /** + * 关联的联系人编号数组 + * + * 关联 {@link CrmContactDO#getId()} + */ + private List contactIds; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml new file mode 100644 index 000000000..10030e0a7 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/yudao-module-erp/pom.xml b/yudao-module-erp/pom.xml new file mode 100644 index 000000000..22fe0eea4 --- /dev/null +++ b/yudao-module-erp/pom.xml @@ -0,0 +1,24 @@ + + + + cn.iocoder.boot + yudao + ${revision} + + + yudao-module-erp-api + yudao-module-erp-biz + + 4.0.0 + yudao-module-erp + pom + + ${project.artifactId} + + erp 包下,企业资源管理(Enterprise Resource Planning)。 + 例如说:采购、销售、库存、财务、产品等等 + + + \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-banner/pom.xml b/yudao-module-erp/yudao-module-erp-api/pom.xml similarity index 69% rename from yudao-framework/yudao-spring-boot-starter-banner/pom.xml rename to yudao-module-erp/yudao-module-erp-api/pom.xml index e740fce5f..961845ce3 100644 --- a/yudao-framework/yudao-spring-boot-starter-banner/pom.xml +++ b/yudao-module-erp/yudao-module-erp-api/pom.xml @@ -3,17 +3,18 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - yudao-framework cn.iocoder.boot + yudao-module-erp ${revision} 4.0.0 - yudao-spring-boot-starter-banner + yudao-module-erp-api jar ${project.artifactId} - Banner 用于在 console 控制台,打印开发文档、接口文档等 - https://github.com/YunaiV/ruoyi-vue-pro + + erp 模块 API,暴露给其它模块调用 + @@ -21,10 +22,12 @@ yudao-common + org.springframework.boot - spring-boot-starter + spring-boot-starter-validation + true - + \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/api/package-info.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/api/package-info.java new file mode 100644 index 000000000..540f18f0e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/api/package-info.java @@ -0,0 +1,4 @@ +/** + * erp API 包,定义暴露给其它模块的 API + */ +package cn.iocoder.yudao.module.erp.api; diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/DictTypeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/DictTypeConstants.java new file mode 100644 index 000000000..36d4df852 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/DictTypeConstants.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.erp.enums; + +/** + * ERP 字典类型的枚举类 + * + * @author 芋道源码 + */ +public interface DictTypeConstants { + + String AUDIT_STATUS = "erp_audit_status"; // 审核状态 + String STOCK_RECORD_BIZ_TYPE = "erp_stock_record_biz_type"; // 库存明细的业务类型 + +} diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErpAuditStatus.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErpAuditStatus.java new file mode 100644 index 000000000..a10147a70 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErpAuditStatus.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.erp.enums; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.Arrays; + +/** + * ERP 审核状态枚举 + * + * TODO 芋艿:目前只有待审批、已审批两个状态,未来接入工作流后,会丰富下:待提交(草稿)=》已提交(待审核)=》审核通过、审核不通过;另外,工作流需要支持“反审核”,把工作流退回到原点; + * + * @author 芋道源码 + */ +@RequiredArgsConstructor +@Getter +public enum ErpAuditStatus implements IntArrayValuable { + + PROCESS(10, "未审核"), // 审核中 + APPROVE(20, "已审核"); // 审核通过 + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpAuditStatus::getStatus).toArray(); + + /** + * 状态 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java new file mode 100644 index 000000000..65f64c2f5 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -0,0 +1,168 @@ +package cn.iocoder.yudao.module.erp.enums; + +import cn.iocoder.yudao.framework.common.exception.ErrorCode; + +/** + * ERP 错误码枚举类 + *

+ * erp 系统,使用 1-030-000-000 段 + */ +public interface ErrorCodeConstants { + + // ========== ERP 供应商(1-030-100-000) ========== + ErrorCode SUPPLIER_NOT_EXISTS = new ErrorCode(1_030_100_000, "供应商不存在"); + ErrorCode SUPPLIER_NOT_ENABLE = new ErrorCode(1_030_100_000, "供应商({})未启用"); + + // ========== ERP 采购订单(1-030-101-000) ========== + ErrorCode PURCHASE_ORDER_NOT_EXISTS = new ErrorCode(1_030_101_000, "采购订单不存在"); + ErrorCode PURCHASE_ORDER_DELETE_FAIL_APPROVE = new ErrorCode(1_030_101_001, "采购订单({})已审核,无法删除"); + ErrorCode PURCHASE_ORDER_PROCESS_FAIL = new ErrorCode(1_030_101_002, "反审核失败,只有已审核的采购订单才能反审核"); + ErrorCode PURCHASE_ORDER_APPROVE_FAIL = new ErrorCode(1_030_101_003, "审核失败,只有未审核的采购订单才能审核"); + ErrorCode PURCHASE_ORDER_NO_EXISTS = new ErrorCode(1_030_101_004, "生成采购单号失败,请重新提交"); + ErrorCode PURCHASE_ORDER_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_101_005, "采购订单({})已审核,无法修改"); + ErrorCode PURCHASE_ORDER_NOT_APPROVE = new ErrorCode(1_030_101_006, "采购订单未审核,无法操作"); + ErrorCode PURCHASE_ORDER_ITEM_IN_FAIL_PRODUCT_EXCEED = new ErrorCode(1_030_101_007, "采购订单项({})超过最大允许入库数量({})"); + ErrorCode PURCHASE_ORDER_PROCESS_FAIL_EXISTS_IN = new ErrorCode(1_030_101_008, "反审核失败,已存在对应的采购入库单"); +ErrorCode PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED = new ErrorCode(1_030_101_009, "采购订单项({})超过最大允许退货数量({})"); + ErrorCode PURCHASE_ORDER_PROCESS_FAIL_EXISTS_RETURN = new ErrorCode(1_030_101_010, "反审核失败,已存在对应的采购退货单"); + + // ========== ERP 采购入库(1-030-102-000) ========== + ErrorCode PURCHASE_IN_NOT_EXISTS = new ErrorCode(1_030_102_000, "采购入库单不存在"); + ErrorCode PURCHASE_IN_DELETE_FAIL_APPROVE = new ErrorCode(1_030_102_001, "采购入库单({})已审核,无法删除"); + ErrorCode PURCHASE_IN_PROCESS_FAIL = new ErrorCode(1_030_102_002, "反审核失败,只有已审核的入库单才能反审核"); + ErrorCode PURCHASE_IN_APPROVE_FAIL = new ErrorCode(1_030_102_003, "审核失败,只有未审核的入库单才能审核"); + ErrorCode PURCHASE_IN_NO_EXISTS = new ErrorCode(1_030_102_004, "生成入库单失败,请重新提交"); + ErrorCode PURCHASE_IN_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_102_005, "采购入库单({})已审核,无法修改"); + ErrorCode PURCHASE_IN_NOT_APPROVE = new ErrorCode(1_030_102_006, "采购入库单未审核,无法操作"); + ErrorCode PURCHASE_IN_FAIL_PAYMENT_PRICE_EXCEED = new ErrorCode(1_030_102_007, "付款金额({})超过采购入库单总金额({})"); + ErrorCode PURCHASE_IN_PROCESS_FAIL_EXISTS_PAYMENT = new ErrorCode(1_030_102_008, "反审核失败,已存在对应的付款单"); + + // ========== ERP 采购退货(1-030-103-000) ========== + ErrorCode PURCHASE_RETURN_NOT_EXISTS = new ErrorCode(1_030_103_000, "采购退货单不存在"); + ErrorCode PURCHASE_RETURN_DELETE_FAIL_APPROVE = new ErrorCode(1_030_103_001, "采购退货单({})已审核,无法删除"); + ErrorCode PURCHASE_RETURN_PROCESS_FAIL = new ErrorCode(1_030_103_002, "反审核失败,只有已审核的退货单才能反审核"); + ErrorCode PURCHASE_RETURN_APPROVE_FAIL = new ErrorCode(1_030_103_003, "审核失败,只有未审核的退货单才能审核"); + ErrorCode PURCHASE_RETURN_NO_EXISTS = new ErrorCode(1_030_103_004, "生成退货单失败,请重新提交"); + ErrorCode PURCHASE_RETURN_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_103_005, "采购退货单({})已审核,无法修改"); + ErrorCode PURCHASE_RETURN_NOT_APPROVE = new ErrorCode(1_030_103_006, "采购退货单未审核,无法操作"); + ErrorCode PURCHASE_RETURN_FAIL_REFUND_PRICE_EXCEED = new ErrorCode(1_030_103_007, "退款金额({})超过采购退货单总金额({})"); + ErrorCode PURCHASE_RETURN_PROCESS_FAIL_EXISTS_REFUND = new ErrorCode(1_030_103_008, "反审核失败,已存在对应的退款单"); + + // ========== ERP 客户(1-030-200-000)========== + ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_020_200_000, "客户不存在"); + ErrorCode CUSTOMER_NOT_ENABLE = new ErrorCode(1_020_200_001, "客户({})未启用"); + + // ========== ERP 销售订单(1-030-201-000) ========== + ErrorCode SALE_ORDER_NOT_EXISTS = new ErrorCode(1_020_201_000, "销售订单不存在"); + ErrorCode SALE_ORDER_DELETE_FAIL_APPROVE = new ErrorCode(1_020_201_001, "销售订单({})已审核,无法删除"); + ErrorCode SALE_ORDER_PROCESS_FAIL = new ErrorCode(1_020_201_002, "反审核失败,只有已审核的销售订单才能反审核"); + ErrorCode SALE_ORDER_APPROVE_FAIL = new ErrorCode(1_020_201_003, "审核失败,只有未审核的销售订单才能审核"); + ErrorCode SALE_ORDER_NO_EXISTS = new ErrorCode(1_020_201_004, "生成销售单号失败,请重新提交"); + ErrorCode SALE_ORDER_UPDATE_FAIL_APPROVE = new ErrorCode(1_020_201_005, "销售订单({})已审核,无法修改"); + ErrorCode SALE_ORDER_NOT_APPROVE = new ErrorCode(1_020_201_006, "销售订单未审核,无法操作"); + ErrorCode SALE_ORDER_ITEM_OUT_FAIL_PRODUCT_EXCEED = new ErrorCode(1_020_201_007, "销售订单项({})超过最大允许出库数量({})"); + ErrorCode SALE_ORDER_PROCESS_FAIL_EXISTS_OUT = new ErrorCode(1_020_201_008, "反审核失败,已存在对应的销售出库单"); + ErrorCode SALE_ORDER_ITEM_RETURN_FAIL_OUT_EXCEED = new ErrorCode(1_020_201_009, "销售订单项({})超过最大允许退货数量({})"); + ErrorCode SALE_ORDER_PROCESS_FAIL_EXISTS_RETURN = new ErrorCode(1_020_201_010, "反审核失败,已存在对应的销售退货单"); + + // ========== ERP 销售出库(1-030-202-000) ========== + ErrorCode SALE_OUT_NOT_EXISTS = new ErrorCode(1_020_202_000, "销售出库单不存在"); + ErrorCode SALE_OUT_DELETE_FAIL_APPROVE = new ErrorCode(1_020_202_001, "销售出库单({})已审核,无法删除"); + ErrorCode SALE_OUT_PROCESS_FAIL = new ErrorCode(1_020_202_002, "反审核失败,只有已审核的出库单才能反审核"); + ErrorCode SALE_OUT_APPROVE_FAIL = new ErrorCode(1_020_202_003, "审核失败,只有未审核的出库单才能审核"); + ErrorCode SALE_OUT_NO_EXISTS = new ErrorCode(1_020_202_004, "生成出库单失败,请重新提交"); + ErrorCode SALE_OUT_UPDATE_FAIL_APPROVE = new ErrorCode(1_020_202_005, "销售出库单({})已审核,无法修改"); + ErrorCode SALE_OUT_NOT_APPROVE = new ErrorCode(1_020_202_006, "销售出库单未审核,无法操作"); + ErrorCode SALE_OUT_FAIL_RECEIPT_PRICE_EXCEED = new ErrorCode(1_020_202_007, "收款金额({})超过销售出库单总金额({})"); + ErrorCode SALE_OUT_PROCESS_FAIL_EXISTS_RECEIPT = new ErrorCode(1_020_202_008, "反审核失败,已存在对应的收款单"); + + // ========== ERP 销售退货(1-030-203-000) ========== + ErrorCode SALE_RETURN_NOT_EXISTS = new ErrorCode(1_020_203_000, "销售退货单不存在"); + ErrorCode SALE_RETURN_DELETE_FAIL_APPROVE = new ErrorCode(1_020_203_001, "销售退货单({})已审核,无法删除"); + ErrorCode SALE_RETURN_PROCESS_FAIL = new ErrorCode(1_020_203_002, "反审核失败,只有已审核的退货单才能反审核"); + ErrorCode SALE_RETURN_APPROVE_FAIL = new ErrorCode(1_020_203_003, "审核失败,只有未审核的退货单才能审核"); + ErrorCode SALE_RETURN_NO_EXISTS = new ErrorCode(1_020_203_004, "生成退货单失败,请重新提交"); + ErrorCode SALE_RETURN_UPDATE_FAIL_APPROVE = new ErrorCode(1_020_203_005, "销售退货单({})已审核,无法修改"); + ErrorCode SALE_RETURN_NOT_APPROVE = new ErrorCode(1_020_203_006, "销售退货单未审核,无法操作"); + ErrorCode SALE_RETURN_FAIL_REFUND_PRICE_EXCEED = new ErrorCode(1_020_203_007, "退款金额({})超过销售退货单总金额({})"); + ErrorCode SALE_RETURN_PROCESS_FAIL_EXISTS_REFUND = new ErrorCode(1_020_203_008, "反审核失败,已存在对应的退款单"); + + // ========== ERP 仓库 1-030-400-000 ========== + ErrorCode WAREHOUSE_NOT_EXISTS = new ErrorCode(1_030_400_000, "仓库不存在"); + ErrorCode WAREHOUSE_NOT_ENABLE = new ErrorCode(1_030_400_001, "仓库({})未启用"); + + // ========== ERP 其它入库单 1-030-401-000 ========== + ErrorCode STOCK_IN_NOT_EXISTS = new ErrorCode(1_030_401_000, "其它入库单不存在"); + ErrorCode STOCK_IN_DELETE_FAIL_APPROVE = new ErrorCode(1_030_401_001, "其它入库单({})已审核,无法删除"); + ErrorCode STOCK_IN_PROCESS_FAIL = new ErrorCode(1_030_401_002, "反审核失败,只有已审核的入库单才能反审核"); + ErrorCode STOCK_IN_APPROVE_FAIL = new ErrorCode(1_030_401_003, "审核失败,只有未审核的入库单才能审核"); + ErrorCode STOCK_IN_NO_EXISTS = new ErrorCode(1_030_401_004, "生成入库单失败,请重新提交"); + ErrorCode STOCK_IN_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_401_005, "其它入库单({})已审核,无法修改"); + + // ========== ERP 其它出库单 1-030-402-000 ========== + ErrorCode STOCK_OUT_NOT_EXISTS = new ErrorCode(1_030_402_000, "其它出库单不存在"); + ErrorCode STOCK_OUT_DELETE_FAIL_APPROVE = new ErrorCode(1_030_402_001, "其它出库单({})已审核,无法删除"); + ErrorCode STOCK_OUT_PROCESS_FAIL = new ErrorCode(1_030_402_002, "反审核失败,只有已审核的出库单才能反审核"); + ErrorCode STOCK_OUT_APPROVE_FAIL = new ErrorCode(1_030_402_003, "审核失败,只有未审核的出库单才能审核"); + ErrorCode STOCK_OUT_NO_EXISTS = new ErrorCode(1_030_402_004, "生成出库单失败,请重新提交"); + ErrorCode STOCK_OUT_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_402_005, "其它出库单({})已审核,无法修改"); + + // ========== ERP 库存调拨单 1-030-403-000 ========== + ErrorCode STOCK_MOVE_NOT_EXISTS = new ErrorCode(1_030_402_000, "库存调拨单不存在"); + ErrorCode STOCK_MOVE_DELETE_FAIL_APPROVE = new ErrorCode(1_030_402_001, "库存调拨单({})已审核,无法删除"); + ErrorCode STOCK_MOVE_PROCESS_FAIL = new ErrorCode(1_030_402_002, "反审核失败,只有已审核的调拨单才能反审核"); + ErrorCode STOCK_MOVE_APPROVE_FAIL = new ErrorCode(1_030_402_003, "审核失败,只有未审核的调拨单才能审核"); + ErrorCode STOCK_MOVE_NO_EXISTS = new ErrorCode(1_030_402_004, "生成调拨号失败,请重新提交"); + ErrorCode STOCK_MOVE_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_402_005, "库存调拨单({})已审核,无法修改"); + + // ========== ERP 库存盘点单 1-030-403-000 ========== + ErrorCode STOCK_CHECK_NOT_EXISTS = new ErrorCode(1_030_403_000, "库存盘点单不存在"); + ErrorCode STOCK_CHECK_DELETE_FAIL_APPROVE = new ErrorCode(1_030_403_001, "库存盘点单({})已审核,无法删除"); + ErrorCode STOCK_CHECK_PROCESS_FAIL = new ErrorCode(1_030_403_002, "反审核失败,只有已审核的盘点单才能反审核"); + ErrorCode STOCK_CHECK_APPROVE_FAIL = new ErrorCode(1_030_403_003, "审核失败,只有未审核的盘点单才能审核"); + ErrorCode STOCK_CHECK_NO_EXISTS = new ErrorCode(1_030_403_004, "生成盘点号失败,请重新提交"); + ErrorCode STOCK_CHECK_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_403_005, "库存盘点单({})已审核,无法修改"); + + // ========== ERP 产品库存 1-030-404-000 ========== + ErrorCode STOCK_COUNT_NEGATIVE = new ErrorCode(1_030_404_000, "操作失败,产品({})所在仓库({})的库存:{},小于变更数量:{}"); + ErrorCode STOCK_COUNT_NEGATIVE2 = new ErrorCode(1_030_404_001, "操作失败,产品({})所在仓库({})的库存不足"); + + // ========== ERP 产品 1-030-500-000 ========== + ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_030_500_000, "产品不存在"); + ErrorCode PRODUCT_NOT_ENABLE = new ErrorCode(1_030_500_001, "产品({})未启用"); + + // ========== ERP 产品分类 1-030-501-000 ========== + ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_030_501_000, "产品分类不存在"); + ErrorCode PRODUCT_CATEGORY_EXITS_CHILDREN = new ErrorCode(1_030_501_001, "存在存在子产品分类,无法删除"); + ErrorCode PRODUCT_CATEGORY_PARENT_NOT_EXITS = new ErrorCode(1_030_501_002,"父级产品分类不存在"); + ErrorCode PRODUCT_CATEGORY_PARENT_ERROR = new ErrorCode(1_030_501_003, "不能设置自己为父产品分类"); + ErrorCode PRODUCT_CATEGORY_NAME_DUPLICATE = new ErrorCode(1_030_501_004, "已经存在该分类名称的产品分类"); + ErrorCode PRODUCT_CATEGORY_PARENT_IS_CHILD = new ErrorCode(1_030_501_005, "不能设置自己的子分类为父分类"); + ErrorCode PRODUCT_CATEGORY_EXITS_PRODUCT = new ErrorCode(1_030_502_002, "存在产品使用该分类,无法删除"); + + // ========== ERP 产品单位 1-030-502-000 ========== + ErrorCode PRODUCT_UNIT_NOT_EXISTS = new ErrorCode(1_030_502_000, "产品单位不存在"); + ErrorCode PRODUCT_UNIT_NAME_DUPLICATE = new ErrorCode(1_030_502_001, "已存在该名字的产品单位"); + ErrorCode PRODUCT_UNIT_EXITS_PRODUCT = new ErrorCode(1_030_502_002, "存在产品使用该单位,无法删除"); + + // ========== ERP 结算账户 1-030-600-000 ========== + ErrorCode ACCOUNT_NOT_EXISTS = new ErrorCode(1_030_600_000, "结算账户不存在"); + ErrorCode ACCOUNT_NOT_ENABLE = new ErrorCode(1_030_600_001, "结算账户({})未启用"); + + // ========== ERP 付款单 1-030-601-000 ========== + ErrorCode FINANCE_PAYMENT_NOT_EXISTS = new ErrorCode(1_030_601_000, "付款单不存在"); + ErrorCode FINANCE_PAYMENT_DELETE_FAIL_APPROVE = new ErrorCode(1_030_601_001, "付款单({})已审核,无法删除"); + ErrorCode FINANCE_PAYMENT_PROCESS_FAIL = new ErrorCode(1_030_601_002, "反审核失败,只有已审核的付款单才能反审核"); + ErrorCode FINANCE_PAYMENT_APPROVE_FAIL = new ErrorCode(1_030_601_003, "审核失败,只有未审核的付款单才能审核"); + ErrorCode FINANCE_PAYMENT_NO_EXISTS = new ErrorCode(1_030_601_004, "生成付款单号失败,请重新提交"); + ErrorCode FINANCE_PAYMENT_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_601_005, "付款单({})已审核,无法修改"); + + // ========== ERP 收款单 1-030-602-000 ========== + ErrorCode FINANCE_RECEIPT_NOT_EXISTS = new ErrorCode(1_030_602_000, "收款单不存在"); + ErrorCode FINANCE_RECEIPT_DELETE_FAIL_APPROVE = new ErrorCode(1_030_602_001, "收款单({})已审核,无法删除"); + ErrorCode FINANCE_RECEIPT_PROCESS_FAIL = new ErrorCode(1_030_602_002, "反审核失败,只有已审核的收款单才能反审核"); + ErrorCode FINANCE_RECEIPT_APPROVE_FAIL = new ErrorCode(1_030_602_003, "审核失败,只有未审核的收款单才能审核"); + ErrorCode FINANCE_RECEIPT_NO_EXISTS = new ErrorCode(1_030_602_004, "生成收款单号失败,请重新提交"); + ErrorCode FINANCE_RECEIPT_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_602_005, "收款单({})已审核,无法修改"); + +} diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/LogRecordConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/LogRecordConstants.java new file mode 100644 index 000000000..73b72c0a9 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/LogRecordConstants.java @@ -0,0 +1,12 @@ +package cn.iocoder.yudao.module.erp.enums; + +/** + * ERP 操作日志枚举 + * 目的:统一管理,也减少 Service 里各种“复杂”字符串 + * + * @author 芋道源码 + */ +public interface LogRecordConstants { + + +} diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/common/ErpBizTypeEnum.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/common/ErpBizTypeEnum.java new file mode 100644 index 000000000..bba2b309b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/common/ErpBizTypeEnum.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.erp.enums.common; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.Arrays; + +/** + * ERP 业务类型枚举 + * + * @author HUIHUI + */ +@RequiredArgsConstructor +@Getter +public enum ErpBizTypeEnum implements IntArrayValuable { + + PURCHASE_ORDER(10, "采购订单"), + PURCHASE_IN(11, "采购入库"), + PURCHASE_RETURN(12, "采购退货"), + + SALE_ORDER(20, "销售订单"), + SALE_OUT(21, "销售订单"), + SALE_RETURN(22, "销售退货"), + ; + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpBizTypeEnum::getType).toArray(); + + /** + * 类型 + */ + private final Integer type; + /** + * 名称 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java new file mode 100644 index 000000000..559bf4ccf --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.erp.enums.stock; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.Arrays; + +/** + * ERP 库存明细 - 业务类型枚举 + * + * @author 芋道源码 + */ +@RequiredArgsConstructor +@Getter +public enum ErpStockRecordBizTypeEnum implements IntArrayValuable { + + OTHER_IN(10, "其它入库"), + OTHER_IN_CANCEL(11, "其它入库(作废)"), + + OTHER_OUT(20, "其它出库"), + OTHER_OUT_CANCEL(21, "其它出库(作废)"), + + MOVE_IN(30, "调拨入库"), + MOVE_IN_CANCEL(31, "调拨入库(作废)"), + MOVE_OUT(32, "调拨出库"), + MOVE_OUT_CANCEL(33, "调拨出库(作废)"), + + CHECK_MORE_IN(40, "盘盈入库"), + CHECK_MORE_IN_CANCEL(41, "盘盈入库(作废)"), + CHECK_LESS_OUT(42, "盘亏出库"), + CHECK_LESS_OUT_CANCEL(43, "盘亏出库(作废)"), + + SALE_OUT(50, "销售出库"), + SALE_OUT_CANCEL(51, "销售出库(作废)"), + + SALE_RETURN(60, "销售退货入库"), + SALE_RETURN_CANCEL(61, "销售退货入库(作废)"), + + PURCHASE_IN(70, "采购入库"), + PURCHASE_IN_CANCEL(71, "采购入库(作废)"), + + PURCHASE_RETURN(80, "采购退货出库"), + PURCHASE_RETURN_CANCEL(81, "采购退货出库(作废)"), + ; + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpStockRecordBizTypeEnum::getType).toArray(); + + /** + * 类型 + */ + private final Integer type; + /** + * 名字 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/pom.xml b/yudao-module-erp/yudao-module-erp-biz/pom.xml new file mode 100644 index 000000000..1d0b44162 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/pom.xml @@ -0,0 +1,77 @@ + + + + cn.iocoder.boot + yudao-module-erp + ${revision} + + 4.0.0 + yudao-module-erp-biz + + ${project.artifactId} + + erp 包下,企业资源管理(Enterprise Resource Planning)。 + 例如说:采购、销售、库存、财务、产品等等 + + + + + cn.iocoder.boot + yudao-module-system-api + ${revision} + + + cn.iocoder.boot + yudao-module-erp-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-redis + + + + + cn.iocoder.boot + yudao-spring-boot-starter-excel + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-dict + + + + + cn.iocoder.boot + yudao-spring-boot-starter-test + + + + + \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java new file mode 100644 index 000000000..066d2ec3e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java @@ -0,0 +1,116 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import 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.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 结算账户") +@RestController +@RequestMapping("/erp/account") +@Validated +public class ErpAccountController { + + @Resource + private ErpAccountService accountService; + + @PostMapping("/create") + @Operation(summary = "创建结算账户") + @PreAuthorize("@ss.hasPermission('erp:account:create')") + public CommonResult createAccount(@Valid @RequestBody ErpAccountSaveReqVO createReqVO) { + return success(accountService.createAccount(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新结算账户") + @PreAuthorize("@ss.hasPermission('erp:account:update')") + public CommonResult updateAccount(@Valid @RequestBody ErpAccountSaveReqVO updateReqVO) { + accountService.updateAccount(updateReqVO); + return success(true); + } + + @PutMapping("/update-default-status") + @Operation(summary = "更新结算账户默认状态") + @Parameters({ + @Parameter(name = "id", description = "编号", required = true), + @Parameter(name = "status", description = "状态", required = true) + }) + public CommonResult updateAccountDefaultStatus(@RequestParam("id") Long id, + @RequestParam("defaultStatus") Boolean defaultStatus) { + accountService.updateAccountDefaultStatus(id, defaultStatus); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除结算账户") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('erp:account:delete')") + public CommonResult deleteAccount(@RequestParam("id") Long id) { + accountService.deleteAccount(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得结算账户") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:account:query')") + public CommonResult getAccount(@RequestParam("id") Long id) { + ErpAccountDO account = accountService.getAccount(id); + return success(BeanUtils.toBean(account, ErpAccountRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得结算账户精简列表", description = "只包含被开启的结算账户,主要用于前端的下拉选项") + public CommonResult> getWarehouseSimpleList() { + List list = accountService.getAccountListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, account -> new ErpAccountRespVO().setId(account.getId()) + .setName(account.getName()).setDefaultStatus(account.getDefaultStatus()))); + } + + @GetMapping("/page") + @Operation(summary = "获得结算账户分页") + @PreAuthorize("@ss.hasPermission('erp:account:query')") + public CommonResult> getAccountPage(@Valid ErpAccountPageReqVO pageReqVO) { + PageResult pageResult = accountService.getAccountPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, ErpAccountRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出结算账户 Excel") + @PreAuthorize("@ss.hasPermission('erp:account:export')") + @OperateLog(type = EXPORT) + public void exportAccountExcel(@Valid ErpAccountPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = accountService.getAccountPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "结算账户.xls", "数据", ErpAccountRespVO.class, + BeanUtils.toBean(list, ErpAccountRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinancePaymentController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinancePaymentController.java new file mode 100644 index 000000000..e7d776b49 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinancePaymentController.java @@ -0,0 +1,153 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; +import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; +import cn.iocoder.yudao.module.erp.service.finance.ErpFinancePaymentService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import 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 java.util.Map; +import java.util.stream.Stream; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 付款单") +@RestController +@RequestMapping("/erp/finance-payment") +@Validated +public class ErpFinancePaymentController { + + @Resource + private ErpFinancePaymentService financePaymentService; + @Resource + private ErpSupplierService supplierService; + @Resource + private ErpAccountService accountService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建付款单") + @PreAuthorize("@ss.hasPermission('erp:finance-payment:create')") + public CommonResult createFinancePayment(@Valid @RequestBody ErpFinancePaymentSaveReqVO createReqVO) { + return success(financePaymentService.createFinancePayment(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新付款单") + @PreAuthorize("@ss.hasPermission('erp:finance-payment:update')") + public CommonResult updateFinancePayment(@Valid @RequestBody ErpFinancePaymentSaveReqVO updateReqVO) { + financePaymentService.updateFinancePayment(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新付款单的状态") + @PreAuthorize("@ss.hasPermission('erp:finance-payment:update-status')") + public CommonResult updateFinancePaymentStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + financePaymentService.updateFinancePaymentStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除付款单") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:finance-payment:delete')") + public CommonResult deleteFinancePayment(@RequestParam("ids") List ids) { + financePaymentService.deleteFinancePayment(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得付款单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:finance-payment:query')") + public CommonResult getFinancePayment(@RequestParam("id") Long id) { + ErpFinancePaymentDO payment = financePaymentService.getFinancePayment(id); + if (payment == null) { + return success(null); + } + List paymentItemList = financePaymentService.getFinancePaymentItemListByPaymentId(id); + return success(BeanUtils.toBean(payment, ErpFinancePaymentRespVO.class, financePaymentVO -> + financePaymentVO.setItems(BeanUtils.toBean(paymentItemList, ErpFinancePaymentRespVO.Item.class)))); + } + + @GetMapping("/page") + @Operation(summary = "获得付款单分页") + @PreAuthorize("@ss.hasPermission('erp:finance-payment:query')") + public CommonResult> getFinancePaymentPage(@Valid ErpFinancePaymentPageReqVO pageReqVO) { + PageResult pageResult = financePaymentService.getFinancePaymentPage(pageReqVO); + return success(buildFinancePaymentVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出付款单 Excel") + @PreAuthorize("@ss.hasPermission('erp:finance-payment:export')") + @OperateLog(type = EXPORT) + public void exportFinancePaymentExcel(@Valid ErpFinancePaymentPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildFinancePaymentVOPageResult(financePaymentService.getFinancePaymentPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "付款单.xls", "数据", ErpFinancePaymentRespVO.class, list); + } + + private PageResult buildFinancePaymentVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 付款项 + List paymentItemList = financePaymentService.getFinancePaymentItemListByPaymentIds( + convertSet(pageResult.getList(), ErpFinancePaymentDO::getId)); + Map> financePaymentItemMap = convertMultiMap(paymentItemList, ErpFinancePaymentItemDO::getPaymentId); + // 1.2 供应商信息 + Map supplierMap = supplierService.getSupplierMap( + convertSet(pageResult.getList(), ErpFinancePaymentDO::getSupplierId)); + // 1.3 结算账户信息 + Map accountMap = accountService.getAccountMap( + convertSet(pageResult.getList(), ErpFinancePaymentDO::getAccountId)); + // 1.4 管理员信息 + Map userMap = adminUserApi.getUserMap(convertListByFlatMap(pageResult.getList(), + contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getFinanceUserId()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpFinancePaymentRespVO.class, payment -> { + payment.setItems(BeanUtils.toBean(financePaymentItemMap.get(payment.getId()), ErpFinancePaymentRespVO.Item.class)); + MapUtils.findAndThen(supplierMap, payment.getSupplierId(), supplier -> payment.setSupplierName(supplier.getName())); + MapUtils.findAndThen(accountMap, payment.getAccountId(), account -> payment.setAccountName(account.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(payment.getCreator()), user -> payment.setCreatorName(user.getNickname())); + MapUtils.findAndThen(userMap, payment.getFinanceUserId(), user -> payment.setFinanceUserName(user.getNickname())); + }); + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinanceReceiptController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinanceReceiptController.java new file mode 100644 index 000000000..7c5233e0f --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinanceReceiptController.java @@ -0,0 +1,153 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt.ErpFinanceReceiptPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt.ErpFinanceReceiptRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt.ErpFinanceReceiptSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; +import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; +import cn.iocoder.yudao.module.erp.service.finance.ErpFinanceReceiptService; +import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import 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 java.util.Map; +import java.util.stream.Stream; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 收款单") +@RestController +@RequestMapping("/erp/finance-receipt") +@Validated +public class ErpFinanceReceiptController { + + @Resource + private ErpFinanceReceiptService financeReceiptService; + @Resource + private ErpCustomerService customerService; + @Resource + private ErpAccountService accountService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建收款单") + @PreAuthorize("@ss.hasPermission('erp:finance-receipt:create')") + public CommonResult createFinanceReceipt(@Valid @RequestBody ErpFinanceReceiptSaveReqVO createReqVO) { + return success(financeReceiptService.createFinanceReceipt(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新收款单") + @PreAuthorize("@ss.hasPermission('erp:finance-receipt:update')") + public CommonResult updateFinanceReceipt(@Valid @RequestBody ErpFinanceReceiptSaveReqVO updateReqVO) { + financeReceiptService.updateFinanceReceipt(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新收款单的状态") + @PreAuthorize("@ss.hasPermission('erp:finance-receipt:update-status')") + public CommonResult updateFinanceReceiptStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + financeReceiptService.updateFinanceReceiptStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除收款单") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:finance-receipt:delete')") + public CommonResult deleteFinanceReceipt(@RequestParam("ids") List ids) { + financeReceiptService.deleteFinanceReceipt(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得收款单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:finance-receipt:query')") + public CommonResult getFinanceReceipt(@RequestParam("id") Long id) { + ErpFinanceReceiptDO receipt = financeReceiptService.getFinanceReceipt(id); + if (receipt == null) { + return success(null); + } + List receiptItemList = financeReceiptService.getFinanceReceiptItemListByReceiptId(id); + return success(BeanUtils.toBean(receipt, ErpFinanceReceiptRespVO.class, financeReceiptVO -> + financeReceiptVO.setItems(BeanUtils.toBean(receiptItemList, ErpFinanceReceiptRespVO.Item.class)))); + } + + @GetMapping("/page") + @Operation(summary = "获得收款单分页") + @PreAuthorize("@ss.hasPermission('erp:finance-receipt:query')") + public CommonResult> getFinanceReceiptPage(@Valid ErpFinanceReceiptPageReqVO pageReqVO) { + PageResult pageResult = financeReceiptService.getFinanceReceiptPage(pageReqVO); + return success(buildFinanceReceiptVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出收款单 Excel") + @PreAuthorize("@ss.hasPermission('erp:finance-receipt:export')") + @OperateLog(type = EXPORT) + public void exportFinanceReceiptExcel(@Valid ErpFinanceReceiptPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildFinanceReceiptVOPageResult(financeReceiptService.getFinanceReceiptPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "收款单.xls", "数据", ErpFinanceReceiptRespVO.class, list); + } + + private PageResult buildFinanceReceiptVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 收款项 + List receiptItemList = financeReceiptService.getFinanceReceiptItemListByReceiptIds( + convertSet(pageResult.getList(), ErpFinanceReceiptDO::getId)); + Map> financeReceiptItemMap = convertMultiMap(receiptItemList, ErpFinanceReceiptItemDO::getReceiptId); + // 1.2 客户信息 + Map customerMap = customerService.getCustomerMap( + convertSet(pageResult.getList(), ErpFinanceReceiptDO::getCustomerId)); + // 1.3 结算账户信息 + Map accountMap = accountService.getAccountMap( + convertSet(pageResult.getList(), ErpFinanceReceiptDO::getAccountId)); + // 1.4 管理员信息 + Map userMap = adminUserApi.getUserMap(convertListByFlatMap(pageResult.getList(), + contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getFinanceUserId()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpFinanceReceiptRespVO.class, receipt -> { + receipt.setItems(BeanUtils.toBean(financeReceiptItemMap.get(receipt.getId()), ErpFinanceReceiptRespVO.Item.class)); + MapUtils.findAndThen(customerMap, receipt.getCustomerId(), customer -> receipt.setCustomerName(customer.getName())); + MapUtils.findAndThen(accountMap, receipt.getAccountId(), account -> receipt.setAccountName(account.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(receipt.getCreator()), user -> receipt.setCreatorName(user.getNickname())); + MapUtils.findAndThen(userMap, receipt.getFinanceUserId(), user -> receipt.setFinanceUserName(user.getNickname())); + }); + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountPageReqVO.java new file mode 100644 index 000000000..3e1fa72f4 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountPageReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account; + +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 = "管理后台 - ERP 结算账户分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpAccountPageReqVO extends PageParam { + + @Schema(description = "账户编码", example = "A88") + private String no; + + @Schema(description = "账户名称", example = "张三") + private String name; + + @Schema(description = "备注", example = "随便") + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountRespVO.java new file mode 100644 index 000000000..a1c2e954d --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountRespVO.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - ERP 结算账户 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpAccountRespVO { + + @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28684") + @ExcelProperty("结算账户编号") + private Long id; + + @Schema(description = "账户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + @ExcelProperty("账户名称") + private String name; + + @Schema(description = "账户编码", example = "A88") + @ExcelProperty("账户编码") + private String no; + + @Schema(description = "备注", example = "随便") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("开启状态") + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("排序") + private Integer sort; + + @Schema(description = "是否默认", example = "1") + @ExcelProperty("是否默认") + private Boolean defaultStatus; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountSaveReqVO.java new file mode 100644 index 000000000..5b698bec6 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountSaveReqVO.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - ERP 结算账户新增/修改 Request VO") +@Data +public class ErpAccountSaveReqVO { + + @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28684") + private Long id; + + @Schema(description = "账户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + @NotEmpty(message = "账户名称不能为空") + private String name; + + @Schema(description = "账户编码", example = "A88") + private String no; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "开启状态不能为空") + @InEnum(value = CommonStatusEnum.class) + private Integer status; + + @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "排序不能为空") + private Integer sort; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentPageReqVO.java new file mode 100644 index 000000000..b5618cadc --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentPageReqVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment; + +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 = "管理后台 - ERP 付款单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpFinancePaymentPageReqVO extends PageParam { + + @Schema(description = "付款单编号", example = "XS001") + private String no; + + @Schema(description = "付款时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] paymentTime; + + @Schema(description = "供应商编号", example = "1724") + private Long supplierId; + + @Schema(description = "创建者", example = "666") + private String creator; + + @Schema(description = "财务人员编号", example = "888") + private String financeUserId; + + @Schema(description = "结算账户编号", example = "31189") + private Long accountId; + + @Schema(description = "付款状态", example = "2") + private Integer status; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "业务编号", example = "123") + private String bizNo; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java new file mode 100644 index 000000000..2eeac5348 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 付款单 Response VO") +@Data +public class ErpFinancePaymentRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23752") + private Long id; + + @Schema(description = "付款单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "FKD888") + private String no; + + @Schema(description = "付款状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; + + @Schema(description = "付款时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime paymentTime; + + @Schema(description = "财务人员编号", example = "19690") + private Long financeUserId; + @Schema(description = "财务人员名称", example = "张三") + private String financeUserName; + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29399") + private Long supplierId; + @Schema(description = "供应商名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小番茄公司") + private String supplierName; + + @Schema(description = "付款账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28989") + private Long accountId; + @Schema(description = "付款账户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + private String accountName; + + @Schema(description = "合计价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "13832") + private BigDecimal totalPrice; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "11600") + private BigDecimal discountPrice; + + @Schema(description = "实际价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + private BigDecimal paymentPrice; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "创建人", example = "芋道") + private String creator; + @Schema(description = "创建人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "付款项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Data + public static class Item { + + @Schema(description = "付款项编号", example = "11756") + private Long id; + + @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer bizType; + + @Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private Long bizId; + + @Schema(description = "业务单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private String bizNo; + + @Schema(description = "应付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + private BigDecimal totalPrice; + + @Schema(description = "已付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + private BigDecimal paidPrice; + + @Schema(description = "本次付款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + @NotNull(message = "本次付款不能为空") + private BigDecimal paymentPrice; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java new file mode 100644 index 000000000..c13e54fb5 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 付款单新增/修改 Request VO") +@Data +public class ErpFinancePaymentSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23752") + private Long id; + + @Schema(description = "付款时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "付款时间不能为空") + private LocalDateTime paymentTime; + + @Schema(description = "财务人员编号", example = "19690") + private Long financeUserId; + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29399") + @NotNull(message = "供应商编号不能为空") + private Long supplierId; + + @Schema(description = "付款账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28989") + @NotNull(message = "付款账户编号不能为空") + private Long accountId; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "11600") + @NotNull(message = "优惠金额不能为空") + private BigDecimal discountPrice; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "付款项列表", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "付款项列表不能为空") + @Valid + private List items; + + @Data + public static class Item { + + @Schema(description = "付款项编号", example = "11756") + private Long id; + + @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "业务类型不能为空") + private Integer bizType; + + @Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @NotNull(message = "业务编号不能为空") + private Long bizId; + + @Schema(description = "已付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + @NotNull(message = "已付金额不能为空") + private BigDecimal paidPrice; + + @Schema(description = "本次付款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + @NotNull(message = "本次付款不能为空") + private BigDecimal paymentPrice; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptPageReqVO.java new file mode 100644 index 000000000..d3e938c66 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptPageReqVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt; + +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 = "管理后台 - ERP 收款单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpFinanceReceiptPageReqVO extends PageParam { + + @Schema(description = "收款单编号", example = "XS001") + private String no; + + @Schema(description = "收款时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] receiptTime; + + @Schema(description = "客户编号", example = "1724") + private Long customerId; + + @Schema(description = "创建者", example = "666") + private String creator; + + @Schema(description = "财务人员编号", example = "888") + private String financeUserId; + + @Schema(description = "收款账户编号", example = "31189") + private Long accountId; + + @Schema(description = "收款状态", example = "2") + private Integer status; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "业务编号", example = "123") + private String bizNo; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java new file mode 100644 index 000000000..cb2b95d34 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 收款单 Response VO") +@Data +public class ErpFinanceReceiptRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23752") + private Long id; + + @Schema(description = "收款单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "FKD888") + private String no; + + @Schema(description = "收款状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; + + @Schema(description = "收款时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime receiptTime; + + @Schema(description = "财务人员编号", example = "19690") + private Long financeUserId; + @Schema(description = "财务人员名称", example = "张三") + private String financeUserName; + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29399") + private Long customerId; + @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小番茄公司") + private String customerName; + + @Schema(description = "收款账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28989") + private Long accountId; + @Schema(description = "收款账户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + private String accountName; + + @Schema(description = "合计价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "13832") + private BigDecimal totalPrice; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "11600") + private BigDecimal discountPrice; + + @Schema(description = "实际价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + private BigDecimal receiptPrice; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "创建人", example = "芋道") + private String creator; + @Schema(description = "创建人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "收款项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Data + public static class Item { + + @Schema(description = "收款项编号", example = "11756") + private Long id; + + @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer bizType; + + @Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private Long bizId; + + @Schema(description = "业务单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private String bizNo; + + @Schema(description = "应收金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + private BigDecimal totalPrice; + + @Schema(description = "已收金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + private BigDecimal receiptedPrice; + + @Schema(description = "本次收款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + @NotNull(message = "本次收款不能为空") + private BigDecimal receiptPrice; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptSaveReqVO.java new file mode 100644 index 000000000..e85912b43 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptSaveReqVO.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 收款单新增/修改 Request VO") +@Data +public class ErpFinanceReceiptSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23752") + private Long id; + + @Schema(description = "收款时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "收款时间不能为空") + private LocalDateTime receiptTime; + + @Schema(description = "财务人员编号", example = "19690") + private Long financeUserId; + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29399") + @NotNull(message = "客户编号不能为空") + private Long customerId; + + @Schema(description = "收款账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28989") + @NotNull(message = "收款账户编号不能为空") + private Long accountId; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "11600") + @NotNull(message = "优惠金额不能为空") + private BigDecimal discountPrice; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "收款项列表", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "收款项列表不能为空") + @Valid + private List items; + + @Data + public static class Item { + + @Schema(description = "收款项编号", example = "11756") + private Long id; + + @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "业务类型不能为空") + private Integer bizType; + + @Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @NotNull(message = "业务编号不能为空") + private Long bizId; + + @Schema(description = "已收金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + @NotNull(message = "已收金额不能为空") + private BigDecimal receiptedPrice; + + @Schema(description = "本次收款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + @NotNull(message = "本次收款不能为空") + private BigDecimal receiptPrice; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductCategoryController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductCategoryController.java new file mode 100644 index 000000000..aaeb7cf9d --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductCategoryController.java @@ -0,0 +1,101 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryListReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategorySaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductCategoryService; +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.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 产品分类") +@RestController +@RequestMapping("/erp/product-category") +@Validated +public class ErpProductCategoryController { + + @Resource + private ErpProductCategoryService productCategoryService; + + @PostMapping("/create") + @Operation(summary = "创建产品分类") + @PreAuthorize("@ss.hasPermission('erp:product-category:create')") + public CommonResult createProductCategory(@Valid @RequestBody ErpProductCategorySaveReqVO createReqVO) { + return success(productCategoryService.createProductCategory(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新产品分类") + @PreAuthorize("@ss.hasPermission('erp:product-category:update')") + public CommonResult updateProductCategory(@Valid @RequestBody ErpProductCategorySaveReqVO updateReqVO) { + productCategoryService.updateProductCategory(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除产品分类") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('erp:product-category:delete')") + public CommonResult deleteProductCategory(@RequestParam("id") Long id) { + productCategoryService.deleteProductCategory(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得产品分类") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:product-category:query')") + public CommonResult getProductCategory(@RequestParam("id") Long id) { + ErpProductCategoryDO category = productCategoryService.getProductCategory(id); + return success(BeanUtils.toBean(category, ErpProductCategoryRespVO.class)); + } + + @GetMapping("/list") + @Operation(summary = "获得产品分类列表") + @PreAuthorize("@ss.hasPermission('erp:product-category:query')") + public CommonResult> getProductCategoryList(@Valid ErpProductCategoryListReqVO listReqVO) { + List list = productCategoryService.getProductCategoryList(listReqVO); + return success(BeanUtils.toBean(list, ErpProductCategoryRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得产品分类精简列表", description = "只包含被开启的分类,主要用于前端的下拉选项") + public CommonResult> getProductCategorySimpleList() { + List list = productCategoryService.getProductCategoryList( + new ErpProductCategoryListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus())); + return success(convertList(list, category -> new ErpProductCategoryRespVO() + .setId(category.getId()).setName(category.getName()).setParentId(category.getParentId()))); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出产品分类 Excel") + @PreAuthorize("@ss.hasPermission('erp:product-category:export')") + @OperateLog(type = EXPORT) + public void exportProductCategoryExcel(@Valid ErpProductCategoryListReqVO listReqVO, + HttpServletResponse response) throws IOException { + List list = productCategoryService.getProductCategoryList(listReqVO); + // 导出 Excel + ExcelUtils.write(response, "产品分类.xls", "数据", ErpProductCategoryRespVO.class, + BeanUtils.toBean(list, ErpProductCategoryRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java new file mode 100644 index 000000000..093a6aa49 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java @@ -0,0 +1,105 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +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.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 产品") +@RestController +@RequestMapping("/erp/product") +@Validated +public class ErpProductController { + + @Resource + private ErpProductService productService; + + @PostMapping("/create") + @Operation(summary = "创建产品") + @PreAuthorize("@ss.hasPermission('erp:product:create')") + public CommonResult createProduct(@Valid @RequestBody ProductSaveReqVO createReqVO) { + return success(productService.createProduct(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新产品") + @PreAuthorize("@ss.hasPermission('erp:product:update')") + public CommonResult updateProduct(@Valid @RequestBody ProductSaveReqVO updateReqVO) { + productService.updateProduct(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除产品") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('erp:product:delete')") + public CommonResult deleteProduct(@RequestParam("id") Long id) { + productService.deleteProduct(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得产品") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:product:query')") + public CommonResult getProduct(@RequestParam("id") Long id) { + ErpProductDO product = productService.getProduct(id); + return success(BeanUtils.toBean(product, ErpProductRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得产品分页") + @PreAuthorize("@ss.hasPermission('erp:product:query')") + public CommonResult> getProductPage(@Valid ErpProductPageReqVO pageReqVO) { + return success(productService.getProductVOPage(pageReqVO)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得产品精简列表", description = "只包含被开启的产品,主要用于前端的下拉选项") + public CommonResult> getProductSimpleList() { + List list = productService.getProductVOListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, product -> new ErpProductRespVO().setId(product.getId()) + .setName(product.getName()).setBarCode(product.getBarCode()) + .setCategoryId(product.getCategoryId()).setCategoryName(product.getCategoryName()) + .setUnitId(product.getUnitId()).setUnitName(product.getUnitName()) + .setPurchasePrice(product.getPurchasePrice()).setSalePrice(product.getSalePrice()).setMinPrice(product.getMinPrice()))); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出产品 Excel") + @PreAuthorize("@ss.hasPermission('erp:product:export')") + @OperateLog(type = EXPORT) + public void exportProductExcel(@Valid ErpProductPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + PageResult pageResult = productService.getProductVOPage(pageReqVO); + // 导出 Excel + ExcelUtils.write(response, "产品.xls", "数据", ErpProductRespVO.class, + pageResult.getList()); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductUnitController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductUnitController.java new file mode 100644 index 000000000..ceb5297d1 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductUnitController.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductUnitService; +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.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 产品单位") +@RestController +@RequestMapping("/erp/product-unit") +@Validated +public class ErpProductUnitController { + + @Resource + private ErpProductUnitService productUnitService; + + @PostMapping("/create") + @Operation(summary = "创建产品单位") + @PreAuthorize("@ss.hasPermission('erp:product-unit:create')") + public CommonResult createProductUnit(@Valid @RequestBody ErpProductUnitSaveReqVO createReqVO) { + return success(productUnitService.createProductUnit(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新产品单位") + @PreAuthorize("@ss.hasPermission('erp:product-unit:update')") + public CommonResult updateProductUnit(@Valid @RequestBody ErpProductUnitSaveReqVO updateReqVO) { + productUnitService.updateProductUnit(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除产品单位") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('erp:product-unit:delete')") + public CommonResult deleteProductUnit(@RequestParam("id") Long id) { + productUnitService.deleteProductUnit(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得产品单位") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:product-unit:query')") + public CommonResult getProductUnit(@RequestParam("id") Long id) { + ErpProductUnitDO productUnit = productUnitService.getProductUnit(id); + return success(BeanUtils.toBean(productUnit, ErpProductUnitRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得产品单位分页") + @PreAuthorize("@ss.hasPermission('erp:product-unit:query')") + public CommonResult> getProductUnitPage(@Valid ErpProductUnitPageReqVO pageReqVO) { + PageResult pageResult = productUnitService.getProductUnitPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, ErpProductUnitRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得产品单位精简列表", description = "只包含被开启的单位,主要用于前端的下拉选项") + public CommonResult> getProductUnitSimpleList() { + List list = productUnitService.getProductUnitListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, unit -> new ErpProductUnitRespVO().setId(unit.getId()).setName(unit.getName()))); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出产品单位 Excel") + @PreAuthorize("@ss.hasPermission('erp:product-unit:export')") + @OperateLog(type = EXPORT) + public void exportProductUnitExcel(@Valid ErpProductUnitPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = productUnitService.getProductUnitPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "产品单位.xls", "数据", ErpProductUnitRespVO.class, + BeanUtils.toBean(list, ErpProductUnitRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryListReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryListReqVO.java new file mode 100644 index 000000000..b9b530e7d --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryListReqVO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.category; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - ERP 产品分类列表 Request VO") +@Data +public class ErpProductCategoryListReqVO { + + @Schema(description = "分类名称", example = "芋艿") + private String name; + + @Schema(description = "开启状态", example = "1") + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java new file mode 100644 index 000000000..23d7d9e8f --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.category; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - ERP 产品分类 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpProductCategoryRespVO { + + @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "5860") + @ExcelProperty("分类编号") + private Long id; + + @Schema(description = "父分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "21829") + @ExcelProperty("父分类编号") + private Long parentId; + + @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @ExcelProperty("分类名称") + private String name; + + @Schema(description = "分类编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "S110") + @ExcelProperty("分类编码") + private String code; + + @Schema(description = "分类排序", example = "10") + @ExcelProperty("分类排序") + private Integer sort; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "开启状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategorySaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategorySaveReqVO.java new file mode 100644 index 000000000..1a5ba4e47 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategorySaveReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.category; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - ERP 产品分类新增/修改 Request VO") +@Data +public class ErpProductCategorySaveReqVO { + + @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "5860") + private Long id; + + @Schema(description = "父分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "21829") + @NotNull(message = "父分类编号不能为空") + private Long parentId; + + @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @NotEmpty(message = "分类名称不能为空") + private String name; + + @Schema(description = "分类编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "S110") + @NotEmpty(message = "分类编码不能为空") + private String code; + + @Schema(description = "分类排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @NotNull(message = "分类排序不能为空") + private Integer sort; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "开启状态不能为空") + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductPageReqVO.java new file mode 100644 index 000000000..de4f8142a --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductPageReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product; + +import lombok.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +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 = "管理后台 - ERP 产品分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpProductPageReqVO extends PageParam { + + @Schema(description = "产品名称", example = "李四") + private String name; + + @Schema(description = "产品分类编号", example = "11161") + private Long categoryId; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java new file mode 100644 index 000000000..9be9bc255 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - ERP 产品 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpProductRespVO { + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15672") + @ExcelProperty("产品编号") + private Long id; + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @ExcelProperty("产品名称") + private String name; + + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "X110") + @ExcelProperty("产品条码") + private String barCode; + + @Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11161") + private Long categoryId; + @Schema(description = "产品分类", requiredMode = Schema.RequiredMode.REQUIRED, example = "水果") + @ExcelProperty("产品分类") + private String categoryName; + + @Schema(description = "单位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8869") + private Long unitId; + @Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "个") + @ExcelProperty("单位") + private String unitName; + + @Schema(description = "产品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty("产品状态") + private Integer status; + + @Schema(description = "产品规格", example = "红色") + @ExcelProperty("产品规格") + private String standard; + + @Schema(description = "产品备注", example = "你猜") + @ExcelProperty("产品备注") + private String remark; + + @Schema(description = "保质期天数", example = "10") + @ExcelProperty("保质期天数") + private Integer expiryDay; + + @Schema(description = "基础重量(kg)", example = "1.00") + @ExcelProperty("基础重量(kg)") + private BigDecimal weight; + + @Schema(description = "采购价格,单位:元", example = "10.30") + @ExcelProperty("采购价格,单位:元") + private BigDecimal purchasePrice; + + @Schema(description = "销售价格,单位:元", example = "74.32") + @ExcelProperty("销售价格,单位:元") + private BigDecimal salePrice; + + @Schema(description = "最低价格,单位:元", example = "161.87") + @ExcelProperty("最低价格,单位:元") + private BigDecimal minPrice; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSaveReqVO.java new file mode 100644 index 000000000..cd34e88d9 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSaveReqVO.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +@Schema(description = "管理后台 - ERP 产品新增/修改 Request VO") +@Data +public class ProductSaveReqVO { + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15672") + private Long id; + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @NotEmpty(message = "产品名称不能为空") + private String name; + + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "X110") + @NotEmpty(message = "产品条码不能为空") + private String barCode; + + @Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11161") + @NotNull(message = "产品分类编号不能为空") + private Long categoryId; + + @Schema(description = "单位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8869") + @NotNull(message = "单位编号不能为空") + private Long unitId; + + @Schema(description = "产品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "产品状态不能为空") + private Integer status; + + @Schema(description = "产品规格", example = "红色") + private String standard; + + @Schema(description = "产品备注", example = "你猜") + private String remark; + + @Schema(description = "保质期天数", example = "10") + private Integer expiryDay; + + @Schema(description = "基础重量(kg)", example = "1.00") + private BigDecimal weight; + + @Schema(description = "采购价格,单位:元", example = "10.30") + private BigDecimal purchasePrice; + + @Schema(description = "销售价格,单位:元", example = "74.32") + private BigDecimal salePrice; + + @Schema(description = "最低价格,单位:元", example = "161.87") + private BigDecimal minPrice; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitPageReqVO.java new file mode 100644 index 000000000..87119c126 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitPageReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit; + +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 = "管理后台 - ERP 产品单位分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpProductUnitPageReqVO extends PageParam { + + @Schema(description = "单位名字", example = "芋艿") + private String name; + + @Schema(description = "单位状态", example = "1") + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java new file mode 100644 index 000000000..06f604920 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - ERP 产品单位 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpProductUnitRespVO { + + @Schema(description = "单位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31254") + @ExcelProperty("单位编号") + private Long id; + + @Schema(description = "单位名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @ExcelProperty("单位名字") + private String name; + + @Schema(description = "单位状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("单位状态") + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitSaveReqVO.java new file mode 100644 index 000000000..dd4547849 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitSaveReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - ERP 产品单位新增/修改 Request VO") +@Data +public class ErpProductUnitSaveReqVO { + + @Schema(description = "单位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31254") + private Long id; + + @Schema(description = "单位名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @NotEmpty(message = "单位名字不能为空") + private String name; + + @Schema(description = "单位状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "单位状态不能为空") + @InEnum(CommonStatusEnum.class) + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseInController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseInController.java new file mode 100644 index 000000000..49a9d3fad --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseInController.java @@ -0,0 +1,165 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in.ErpPurchaseInPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in.ErpPurchaseInRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in.ErpPurchaseInSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseInService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import 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.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 采购入库") +@RestController +@RequestMapping("/erp/purchase-in") +@Validated +public class ErpPurchaseInController { + + @Resource + private ErpPurchaseInService purchaseInService; + @Resource + private ErpStockService stockService; + @Resource + private ErpProductService productService; + @Resource + private ErpSupplierService supplierService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建采购入库") + @PreAuthorize("@ss.hasPermission('erp:purchase-in:create')") + public CommonResult createPurchaseIn(@Valid @RequestBody ErpPurchaseInSaveReqVO createReqVO) { + return success(purchaseInService.createPurchaseIn(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新采购入库") + @PreAuthorize("@ss.hasPermission('erp:purchase-in:update')") + public CommonResult updatePurchaseIn(@Valid @RequestBody ErpPurchaseInSaveReqVO updateReqVO) { + purchaseInService.updatePurchaseIn(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新采购入库的状态") + @PreAuthorize("@ss.hasPermission('erp:purchase-in:update-status')") + public CommonResult updatePurchaseInStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + purchaseInService.updatePurchaseInStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除采购入库") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:purchase-in:delete')") + public CommonResult deletePurchaseIn(@RequestParam("ids") List ids) { + purchaseInService.deletePurchaseIn(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得采购入库") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:purchase-in:query')") + public CommonResult getPurchaseIn(@RequestParam("id") Long id) { + ErpPurchaseInDO purchaseIn = purchaseInService.getPurchaseIn(id); + if (purchaseIn == null) { + return success(null); + } + List purchaseInItemList = purchaseInService.getPurchaseInItemListByInId(id); + Map productMap = productService.getProductVOMap( + convertSet(purchaseInItemList, ErpPurchaseInItemDO::getProductId)); + return success(BeanUtils.toBean(purchaseIn, ErpPurchaseInRespVO.class, purchaseInVO -> + purchaseInVO.setItems(BeanUtils.toBean(purchaseInItemList, ErpPurchaseInRespVO.Item.class, item -> { + ErpStockDO stock = stockService.getStock(item.getProductId(), item.getWarehouseId()); + item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO); + MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())); + })))); + } + + @GetMapping("/page") + @Operation(summary = "获得采购入库分页") + @PreAuthorize("@ss.hasPermission('erp:purchase-in:query')") + public CommonResult> getPurchaseInPage(@Valid ErpPurchaseInPageReqVO pageReqVO) { + PageResult pageResult = purchaseInService.getPurchaseInPage(pageReqVO); + return success(buildPurchaseInVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出采购入库 Excel") + @PreAuthorize("@ss.hasPermission('erp:purchase-in:export')") + @OperateLog(type = EXPORT) + public void exportPurchaseInExcel(@Valid ErpPurchaseInPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildPurchaseInVOPageResult(purchaseInService.getPurchaseInPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "采购入库.xls", "数据", ErpPurchaseInRespVO.class, list); + } + + private PageResult buildPurchaseInVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 入库项 + List purchaseInItemList = purchaseInService.getPurchaseInItemListByInIds( + convertSet(pageResult.getList(), ErpPurchaseInDO::getId)); + Map> purchaseInItemMap = convertMultiMap(purchaseInItemList, ErpPurchaseInItemDO::getInId); + // 1.2 产品信息 + Map productMap = productService.getProductVOMap( + convertSet(purchaseInItemList, ErpPurchaseInItemDO::getProductId)); + // 1.3 供应商信息 + Map supplierMap = supplierService.getSupplierMap( + convertSet(pageResult.getList(), ErpPurchaseInDO::getSupplierId)); + // 1.4 管理员信息 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), purchaseIn -> Long.parseLong(purchaseIn.getCreator()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpPurchaseInRespVO.class, purchaseIn -> { + purchaseIn.setItems(BeanUtils.toBean(purchaseInItemMap.get(purchaseIn.getId()), ErpPurchaseInRespVO.Item.class, + item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); + purchaseIn.setProductNames(CollUtil.join(purchaseIn.getItems(), ",", ErpPurchaseInRespVO.Item::getProductName)); + MapUtils.findAndThen(supplierMap, purchaseIn.getSupplierId(), supplier -> purchaseIn.setSupplierName(supplier.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(purchaseIn.getCreator()), user -> purchaseIn.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java new file mode 100644 index 000000000..9a3c4d802 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java @@ -0,0 +1,164 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseOrderService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import 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.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 采购订单") +@RestController +@RequestMapping("/erp/purchase-order") +@Validated +public class ErpPurchaseOrderController { + + @Resource + private ErpPurchaseOrderService purchaseOrderService; + @Resource + private ErpStockService stockService; + @Resource + private ErpProductService productService; + @Resource + private ErpSupplierService supplierService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建采购订单") + @PreAuthorize("@ss.hasPermission('erp:purchase-create:create')") + public CommonResult createPurchaseOrder(@Valid @RequestBody ErpPurchaseOrderSaveReqVO createReqVO) { + return success(purchaseOrderService.createPurchaseOrder(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新采购订单") + @PreAuthorize("@ss.hasPermission('erp:purchase-create:update')") + public CommonResult updatePurchaseOrder(@Valid @RequestBody ErpPurchaseOrderSaveReqVO updateReqVO) { + purchaseOrderService.updatePurchaseOrder(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新采购订单的状态") + @PreAuthorize("@ss.hasPermission('erp:purchase-create:update-status')") + public CommonResult updatePurchaseOrderStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + purchaseOrderService.updatePurchaseOrderStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除采购订单") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:purchase-create:delete')") + public CommonResult deletePurchaseOrder(@RequestParam("ids") List ids) { + purchaseOrderService.deletePurchaseOrder(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得采购订单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:purchase-create:query')") + public CommonResult getPurchaseOrder(@RequestParam("id") Long id) { + ErpPurchaseOrderDO purchaseOrder = purchaseOrderService.getPurchaseOrder(id); + if (purchaseOrder == null) { + return success(null); + } + List purchaseOrderItemList = purchaseOrderService.getPurchaseOrderItemListByOrderId(id); + Map productMap = productService.getProductVOMap( + convertSet(purchaseOrderItemList, ErpPurchaseOrderItemDO::getProductId)); + return success(BeanUtils.toBean(purchaseOrder, ErpPurchaseOrderRespVO.class, purchaseOrderVO -> + purchaseOrderVO.setItems(BeanUtils.toBean(purchaseOrderItemList, ErpPurchaseOrderRespVO.Item.class, item -> { + BigDecimal purchaseCount = stockService.getStockCount(item.getProductId()); + item.setStockCount(purchaseCount != null ? purchaseCount : BigDecimal.ZERO); + MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())); + })))); + } + + @GetMapping("/page") + @Operation(summary = "获得采购订单分页") + @PreAuthorize("@ss.hasPermission('erp:purchase-create:query')") + public CommonResult> getPurchaseOrderPage(@Valid ErpPurchaseOrderPageReqVO pageReqVO) { + PageResult pageResult = purchaseOrderService.getPurchaseOrderPage(pageReqVO); + return success(buildPurchaseOrderVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出采购订单 Excel") + @PreAuthorize("@ss.hasPermission('erp:purchase-create:export')") + @OperateLog(type = EXPORT) + public void exportPurchaseOrderExcel(@Valid ErpPurchaseOrderPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildPurchaseOrderVOPageResult(purchaseOrderService.getPurchaseOrderPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "采购订单.xls", "数据", ErpPurchaseOrderRespVO.class, list); + } + + private PageResult buildPurchaseOrderVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 订单项 + List purchaseOrderItemList = purchaseOrderService.getPurchaseOrderItemListByOrderIds( + convertSet(pageResult.getList(), ErpPurchaseOrderDO::getId)); + Map> purchaseOrderItemMap = convertMultiMap(purchaseOrderItemList, ErpPurchaseOrderItemDO::getOrderId); + // 1.2 产品信息 + Map productMap = productService.getProductVOMap( + convertSet(purchaseOrderItemList, ErpPurchaseOrderItemDO::getProductId)); + // 1.3 供应商信息 + Map supplierMap = supplierService.getSupplierMap( + convertSet(pageResult.getList(), ErpPurchaseOrderDO::getSupplierId)); + // 1.4 管理员信息 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), purchaseOrder -> Long.parseLong(purchaseOrder.getCreator()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpPurchaseOrderRespVO.class, purchaseOrder -> { + purchaseOrder.setItems(BeanUtils.toBean(purchaseOrderItemMap.get(purchaseOrder.getId()), ErpPurchaseOrderRespVO.Item.class, + item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); + purchaseOrder.setProductNames(CollUtil.join(purchaseOrder.getItems(), ",", ErpPurchaseOrderRespVO.Item::getProductName)); + MapUtils.findAndThen(supplierMap, purchaseOrder.getSupplierId(), supplier -> purchaseOrder.setSupplierName(supplier.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(purchaseOrder.getCreator()), user -> purchaseOrder.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseReturnController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseReturnController.java new file mode 100644 index 000000000..bb26e213e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseReturnController.java @@ -0,0 +1,165 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns.ErpPurchaseReturnPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns.ErpPurchaseReturnRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns.ErpPurchaseReturnSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseReturnService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import 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.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 采购退货") +@RestController +@RequestMapping("/erp/purchase-return") +@Validated +public class ErpPurchaseReturnController { + + @Resource + private ErpPurchaseReturnService purchaseReturnService; + @Resource + private ErpStockService stockService; + @Resource + private ErpProductService productService; + @Resource + private ErpSupplierService supplierService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建采购退货") + @PreAuthorize("@ss.hasPermission('erp:purchase-return:create')") + public CommonResult createPurchaseReturn(@Valid @RequestBody ErpPurchaseReturnSaveReqVO createReqVO) { + return success(purchaseReturnService.createPurchaseReturn(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新采购退货") + @PreAuthorize("@ss.hasPermission('erp:purchase-return:update')") + public CommonResult updatePurchaseReturn(@Valid @RequestBody ErpPurchaseReturnSaveReqVO updateReqVO) { + purchaseReturnService.updatePurchaseReturn(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新采购退货的状态") + @PreAuthorize("@ss.hasPermission('erp:purchase-return:update-status')") + public CommonResult updatePurchaseReturnStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + purchaseReturnService.updatePurchaseReturnStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除采购退货") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:purchase-return:delete')") + public CommonResult deletePurchaseReturn(@RequestParam("ids") List ids) { + purchaseReturnService.deletePurchaseReturn(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得采购退货") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:purchase-return:query')") + public CommonResult getPurchaseReturn(@RequestParam("id") Long id) { + ErpPurchaseReturnDO purchaseReturn = purchaseReturnService.getPurchaseReturn(id); + if (purchaseReturn == null) { + return success(null); + } + List purchaseReturnItemList = purchaseReturnService.getPurchaseReturnItemListByReturnId(id); + Map productMap = productService.getProductVOMap( + convertSet(purchaseReturnItemList, ErpPurchaseReturnItemDO::getProductId)); + return success(BeanUtils.toBean(purchaseReturn, ErpPurchaseReturnRespVO.class, purchaseReturnVO -> + purchaseReturnVO.setItems(BeanUtils.toBean(purchaseReturnItemList, ErpPurchaseReturnRespVO.Item.class, item -> { + ErpStockDO stock = stockService.getStock(item.getProductId(), item.getWarehouseId()); + item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO); + MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())); + })))); + } + + @GetMapping("/page") + @Operation(summary = "获得采购退货分页") + @PreAuthorize("@ss.hasPermission('erp:purchase-return:query')") + public CommonResult> getPurchaseReturnPage(@Valid ErpPurchaseReturnPageReqVO pageReqVO) { + PageResult pageResult = purchaseReturnService.getPurchaseReturnPage(pageReqVO); + return success(buildPurchaseReturnVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出采购退货 Excel") + @PreAuthorize("@ss.hasPermission('erp:purchase-return:export')") + @OperateLog(type = EXPORT) + public void exportPurchaseReturnExcel(@Valid ErpPurchaseReturnPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildPurchaseReturnVOPageResult(purchaseReturnService.getPurchaseReturnPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "采购退货.xls", "数据", ErpPurchaseReturnRespVO.class, list); + } + + private PageResult buildPurchaseReturnVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 退货项 + List purchaseReturnItemList = purchaseReturnService.getPurchaseReturnItemListByReturnIds( + convertSet(pageResult.getList(), ErpPurchaseReturnDO::getId)); + Map> purchaseReturnItemMap = convertMultiMap(purchaseReturnItemList, ErpPurchaseReturnItemDO::getReturnId); + // 1.2 产品信息 + Map productMap = productService.getProductVOMap( + convertSet(purchaseReturnItemList, ErpPurchaseReturnItemDO::getProductId)); + // 1.3 供应商信息 + Map supplierMap = supplierService.getSupplierMap( + convertSet(pageResult.getList(), ErpPurchaseReturnDO::getSupplierId)); + // 1.4 管理员信息 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), purchaseReturn -> Long.parseLong(purchaseReturn.getCreator()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpPurchaseReturnRespVO.class, purchaseReturn -> { + purchaseReturn.setItems(BeanUtils.toBean(purchaseReturnItemMap.get(purchaseReturn.getId()), ErpPurchaseReturnRespVO.Item.class, + item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); + purchaseReturn.setProductNames(CollUtil.join(purchaseReturn.getItems(), ",", ErpPurchaseReturnRespVO.Item::getProductName)); + MapUtils.findAndThen(supplierMap, purchaseReturn.getSupplierId(), supplier -> purchaseReturn.setSupplierName(supplier.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(purchaseReturn.getCreator()), user -> purchaseReturn.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpSupplierController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpSupplierController.java new file mode 100644 index 000000000..538cae927 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpSupplierController.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; +import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; +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.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 供应商") +@RestController +@RequestMapping("/erp/supplier") +@Validated +public class ErpSupplierController { + + @Resource + private ErpSupplierService supplierService; + + @PostMapping("/create") + @Operation(summary = "创建供应商") + @PreAuthorize("@ss.hasPermission('erp:supplier:create')") + public CommonResult createSupplier(@Valid @RequestBody ErpSupplierSaveReqVO createReqVO) { + return success(supplierService.createSupplier(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新供应商") + @PreAuthorize("@ss.hasPermission('erp:supplier:update')") + public CommonResult updateSupplier(@Valid @RequestBody ErpSupplierSaveReqVO updateReqVO) { + supplierService.updateSupplier(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除供应商") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('erp:supplier:delete')") + public CommonResult deleteSupplier(@RequestParam("id") Long id) { + supplierService.deleteSupplier(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得供应商") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:supplier:query')") + public CommonResult getSupplier(@RequestParam("id") Long id) { + ErpSupplierDO supplier = supplierService.getSupplier(id); + return success(BeanUtils.toBean(supplier, ErpSupplierRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得供应商分页") + @PreAuthorize("@ss.hasPermission('erp:supplier:query')") + public CommonResult> getSupplierPage(@Valid ErpSupplierPageReqVO pageReqVO) { + PageResult pageResult = supplierService.getSupplierPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, ErpSupplierRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得供应商精简列表", description = "只包含被开启的供应商,主要用于前端的下拉选项") + public CommonResult> getSupplierSimpleList() { + List list = supplierService.getSupplierListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, supplier -> new ErpSupplierRespVO().setId(supplier.getId()).setName(supplier.getName()))); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出供应商 Excel") + @PreAuthorize("@ss.hasPermission('erp:supplier:export')") + @OperateLog(type = EXPORT) + public void exportSupplierExcel(@Valid ErpSupplierPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = supplierService.getSupplierPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "供应商.xls", "数据", ErpSupplierRespVO.class, + BeanUtils.toBean(list, ErpSupplierRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInPageReqVO.java new file mode 100644 index 000000000..e84607ce4 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInPageReqVO.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in; + +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 = "管理后台 - ERP 采购入库分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpPurchaseInPageReqVO extends PageParam { + + public static final Integer PAYMENT_STATUS_NONE = 0; + public static final Integer PAYMENT_STATUS_PART = 1; + public static final Integer PAYMENT_STATUS_ALL = 2; + + @Schema(description = "采购单编号", example = "XS001") + private String no; + + @Schema(description = "供应商编号", example = "1724") + private Long supplierId; + + @Schema(description = "入库时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] inTime; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "入库状态", example = "2") + private Integer status; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "产品编号", example = "1") + private Long productId; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "结算账号编号", example = "1") + private Long accountId; + + @Schema(description = "付款状态", example = "1") + private Integer paymentStatus; + + @Schema(description = "是否可付款", example = "true") + private Boolean paymentEnable; // 对应 paymentStatus = [0, 1] + + @Schema(description = "采购单号", example = "1") + private String orderNo; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java new file mode 100644 index 000000000..530269df9 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java @@ -0,0 +1,145 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 采购入库 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpPurchaseInRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "入库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + @ExcelProperty("入库单编号") + private String no; + + @Schema(description = "入库状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty("入库状态") + private Integer status; + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1724") + private Long supplierId; + @Schema(description = "供应商名称", example = "芋道") + @ExcelProperty("供应商名称") + private String supplierName; + + @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "311.89") + @ExcelProperty("结算账户编号") + private Long accountId; + + @Schema(description = "入库时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("入库时间") + private LocalDateTime inTime; + + @Schema(description = "采购订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + private Long orderId; + @Schema(description = "采购订单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + private String orderNo; + + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") + @ExcelProperty("合计数量") + private BigDecimal totalCount; + @Schema(description = "最终合计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @ExcelProperty("最终合计价格") + private BigDecimal totalPrice; + @Schema(description = "已付款金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal paymentPrice; + + @Schema(description = "合计产品价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalProductPrice; + + @Schema(description = "合计税额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalTaxPrice; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal discountPrice; + + @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal otherPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + @ExcelProperty("附件地址") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建人", example = "芋道") + private String creator; + @Schema(description = "创建人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "入库项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("产品信息") + private String productNames; + + @Data + public static class Item { + + @Schema(description = "入库项编号", example = "11756") + private Long id; + + @Schema(description = "采购订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private Long orderItemId; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "税额,单位:元", example = "100.00") + private BigDecimal taxPrice; + + @Schema(description = "备注", example = "随便") + private String remark; + + // ========== 关联字段 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") + private String productBarCode; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") + private String productUnitName; + + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal stockCount; // 该字段仅仅在“详情”和“编辑”时使用 + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInSaveReqVO.java new file mode 100644 index 000000000..b4aa63006 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInSaveReqVO.java @@ -0,0 +1,81 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 采购入库新增/修改 Request VO") +@Data +public class ErpPurchaseInSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + private Long id; + + @Schema(description = "结算账户编号", example = "31189") + private Long accountId; + + @Schema(description = "入库时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "入库时间不能为空") + private LocalDateTime inTime; + + @Schema(description = "采购订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + @NotNull(message = "采购订单编号不能为空") + private Long orderId; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "其它金额,单位:元", example = "7127") + private BigDecimal otherPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "入库清单列表") + private List items; + + @Data + public static class Item { + + @Schema(description = "入库项编号", example = "11756") + private Long id; + + @Schema(description = "采购订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @NotNull(message = "采购订单项编号不能为空") + private Long orderItemId; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "仓库编号不能为空") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品编号不能为空") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品单位单位不能为空") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderPageReqVO.java new file mode 100644 index 000000000..8bf70d427 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderPageReqVO.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order; + +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 = "管理后台 - ERP 采购订单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpPurchaseOrderPageReqVO extends PageParam { + + /** + * 入库状态 - 无 + */ + public static final Integer IN_STATUS_NONE = 0; + /** + * 入库状态 - 部分 + */ + public static final Integer IN_STATUS_PART = 1; + /** + * 入库状态 - 全部 + */ + public static final Integer IN_STATUS_ALL = 2; + + /** + * 退货状态 - 无 + */ + public static final Integer RETURN_STATUS_NONE = 0; + /** + * 退货状态 - 部分 + */ + public static final Integer RETURN_STATUS_PART = 1; + /** + * 退货状态 - 全部 + */ + public static final Integer RETURN_STATUS_ALL = 2; + + @Schema(description = "采购单编号", example = "XS001") + private String no; + + @Schema(description = "供应商编号", example = "1724") + private Long supplierId; + + @Schema(description = "采购时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] orderTime; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "采购状态", example = "2") + private Integer status; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "产品编号", example = "1") + private Long productId; + + @Schema(description = "入库状态", example = "2") + private Integer inStatus; + + @Schema(description = "退货状态", example = "2") + private Integer returnStatus; + + @Schema(description = "是否可入库", example = "true") + private Boolean inEnable; + + @Schema(description = "是否可退货", example = "true") + private Boolean returnEnable; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java new file mode 100644 index 000000000..2e5751635 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java @@ -0,0 +1,152 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 采购订单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpPurchaseOrderRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "采购单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + @ExcelProperty("采购单编号") + private String no; + + @Schema(description = "采购状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty("采购状态") + private Integer status; + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1724") + private Long supplierId; + @Schema(description = "供应商名称", example = "芋道") + @ExcelProperty("供应商名称") + private String supplierName; + + @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "311.89") + @ExcelProperty("结算账户编号") + private Long accountId; + + @Schema(description = "采购时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("采购时间") + private LocalDateTime orderTime; + + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") + @ExcelProperty("合计数量") + private BigDecimal totalCount; + @Schema(description = "最终合计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @ExcelProperty("最终合计价格") + private BigDecimal totalPrice; + + @Schema(description = "合计产品价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalProductPrice; + + @Schema(description = "合计税额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalTaxPrice; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal discountPrice; + + @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal depositPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + @ExcelProperty("附件地址") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建人", example = "芋道") + private String creator; + @Schema(description = "创建人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "订单项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("产品信息") + private String productNames; + + // ========== 采购入库 ========== + + @Schema(description = "采购入库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal inCount; + + // ========== 采购退货(出库)) ========== + + @Schema(description = "采购退货数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal returnCount; + + @Data + public static class Item { + + @Schema(description = "订单项编号", example = "11756") + private Long id; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "税额,单位:元", example = "100.00") + private BigDecimal taxPrice; + + @Schema(description = "备注", example = "随便") + private String remark; + + // ========== 采购入库 ========== + + @Schema(description = "采购入库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal inCount; + + // ========== 采购退货(入库)) ========== + + @Schema(description = "采购退货数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal returnCount; + + // ========== 关联字段 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") + private String productBarCode; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") + private String productUnitName; + + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal stockCount; // 该字段仅仅在“详情”和“编辑”时使用 + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderSaveReqVO.java new file mode 100644 index 000000000..78b4d2e0e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderSaveReqVO.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 采购订单新增/修改 Request VO") +@Data +public class ErpPurchaseOrderSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + private Long id; + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1724") + @NotNull(message = "供应商编号不能为空") + private Long supplierId; + + @Schema(description = "结算账户编号", example = "31189") + private Long accountId; + + @Schema(description = "采购时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "采购时间不能为空") + private LocalDateTime orderTime; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "定金金额,单位:元", example = "7127") + private BigDecimal depositPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "订单清单列表") + private List items; + + @Data + public static class Item { + + @Schema(description = "订单项编号", example = "11756") + private Long id; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品编号不能为空") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品单位单位不能为空") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnPageReqVO.java new file mode 100644 index 000000000..a534d2e3e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnPageReqVO.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns; + +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 = "管理后台 - ERP 采购退货分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpPurchaseReturnPageReqVO extends PageParam { + + public static final Integer REFUND_STATUS_NONE = 0; + public static final Integer REFUND_STATUS_PART = 1; + public static final Integer REFUND_STATUS_ALL = 2; + + @Schema(description = "采购单编号", example = "XS001") + private String no; + + @Schema(description = "供应商编号", example = "1724") + private Long supplierId; + + @Schema(description = "退货时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] returnTime; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "退货状态", example = "2") + private Integer status; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "产品编号", example = "1") + private Long productId; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "结算账号编号", example = "1") + private Long accountId; + + @Schema(description = "采购单号", example = "1") + private String orderNo; + + @Schema(description = "退款状态", example = "1") + private Integer refundStatus; + + @Schema(description = "是否可退款", example = "true") + private Boolean refundEnable; // 对应 refundStatus = [0, 1] + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java new file mode 100644 index 000000000..1d20e43f7 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java @@ -0,0 +1,145 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 采购退货 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpPurchaseReturnRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "退货单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + @ExcelProperty("退货单编号") + private String no; + + @Schema(description = "退货状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty("退货状态") + private Integer status; + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1724") + private Long supplierId; + @Schema(description = "供应商名称", example = "芋道") + @ExcelProperty("供应商名称") + private String supplierName; + + @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "311.89") + @ExcelProperty("结算账户编号") + private Long accountId; + + @Schema(description = "退货时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("退货时间") + private LocalDateTime returnTime; + + @Schema(description = "采购订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + private Long orderId; + @Schema(description = "采购订单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + private String orderNo; + + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") + @ExcelProperty("合计数量") + private BigDecimal totalCount; + @Schema(description = "最终合计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @ExcelProperty("最终合计价格") + private BigDecimal totalPrice; + @Schema(description = "已退款金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal refundPrice; + + @Schema(description = "合计产品价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalProductPrice; + + @Schema(description = "合计税额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalTaxPrice; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal discountPrice; + + @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal otherPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + @ExcelProperty("附件地址") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建人", example = "芋道") + private String creator; + @Schema(description = "创建人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "退货项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("产品信息") + private String productNames; + + @Data + public static class Item { + + @Schema(description = "退货项编号", example = "11756") + private Long id; + + @Schema(description = "采购订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private Long orderItemId; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "税额,单位:元", example = "100.00") + private BigDecimal taxPrice; + + @Schema(description = "备注", example = "随便") + private String remark; + + // ========== 关联字段 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") + private String productBarCode; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") + private String productUnitName; + + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal stockCount; // 该字段仅仅在“详情”和“编辑”时使用 + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnSaveReqVO.java new file mode 100644 index 000000000..0d6e55461 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnSaveReqVO.java @@ -0,0 +1,81 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 采购退货新增/修改 Request VO") +@Data +public class ErpPurchaseReturnSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + private Long id; + + @Schema(description = "结算账户编号", example = "31189") + private Long accountId; + + @Schema(description = "退货时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "退货时间不能为空") + private LocalDateTime returnTime; + + @Schema(description = "采购订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + @NotNull(message = "采购订单编号不能为空") + private Long orderId; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "其它金额,单位:元", example = "7127") + private BigDecimal otherPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "退货清单列表") + private List items; + + @Data + public static class Item { + + @Schema(description = "退货项编号", example = "11756") + private Long id; + + @Schema(description = "采购订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @NotNull(message = "采购订单项编号不能为空") + private Long orderItemId; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "仓库编号不能为空") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品编号不能为空") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品单位单位不能为空") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierPageReqVO.java new file mode 100644 index 000000000..229ab63d9 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierPageReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier; + +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 = "管理后台 - ERP 供应商分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpSupplierPageReqVO extends PageParam { + + @Schema(description = "供应商名称", example = "芋道源码") + private String name; + + @Schema(description = "手机号码", example = "15601691300") + private String mobile; + + @Schema(description = "联系电话", example = "18818288888") + private String telephone; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierRespVO.java new file mode 100644 index 000000000..5ba5892c1 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierRespVO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - ERP 供应商 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpSupplierRespVO { + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17791") + @ExcelProperty("供应商编号") + private Long id; + + @Schema(description = "供应商名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") + @ExcelProperty("供应商名称") + private String name; + + @Schema(description = "联系人", example = "芋艿") + @ExcelProperty("联系人") + private String contact; + + @Schema(description = "手机号码", example = "15601691300") + @ExcelProperty("手机号码") + private String mobile; + + @Schema(description = "联系电话", example = "18818288888") + @ExcelProperty("联系电话") + private String telephone; + + @Schema(description = "电子邮箱", example = "76853@qq.com") + @ExcelProperty("电子邮箱") + private String email; + + @Schema(description = "传真", example = "20 7123 4567") + @ExcelProperty("传真") + private String fax; + + @Schema(description = "备注", example = "你猜") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "开启状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty("排序") + private Integer sort; + + @Schema(description = "纳税人识别号", example = "91130803MA098BY05W") + @ExcelProperty("纳税人识别号") + private String taxNo; + + @Schema(description = "税率", example = "10") + @ExcelProperty("税率") + private BigDecimal taxPercent; + + @Schema(description = "开户行", example = "张三") + @ExcelProperty("开户行") + private String bankName; + + @Schema(description = "开户账号", example = "622908212277228617") + @ExcelProperty("开户账号") + private String bankAccount; + + @Schema(description = "开户地址", example = "兴业银行浦东支行") + @ExcelProperty("开户地址") + private String bankAddress; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierSaveReqVO.java new file mode 100644 index 000000000..3c26ba9c1 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierSaveReqVO.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +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 io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +@Schema(description = "管理后台 - ERP 供应商新增/修改 Request VO") +@Data +public class ErpSupplierSaveReqVO { + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17791") + private Long id; + + @Schema(description = "供应商名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") + @NotEmpty(message = "供应商名称不能为空") + private String name; + + @Schema(description = "联系人", example = "芋艿") + private String contact; + + @Schema(description = "手机号码", example = "15601691300") + @Mobile + private String mobile; + + @Schema(description = "联系电话", example = "18818288888") + @Telephone + private String telephone; + + @Schema(description = "电子邮箱", example = "76853@qq.com") + @Email + private String email; + + @Schema(description = "传真", example = "20 7123 4567") + private String fax; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "开启状态不能为空") + @InEnum(value = CommonStatusEnum.class) + private Integer status; + + @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @NotNull(message = "排序不能为空") + private Integer sort; + + @Schema(description = "纳税人识别号", example = "91130803MA098BY05W") + private String taxNo; + + @Schema(description = "税率", example = "10") + private BigDecimal taxPercent; + + @Schema(description = "开户行", example = "张三") + private String bankName; + + @Schema(description = "开户账号", example = "622908212277228617") + private String bankAccount; + + @Schema(description = "开户地址", example = "兴业银行浦东支行") + private String bankAddress; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpCustomerController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpCustomerController.java new file mode 100644 index 000000000..0b131c384 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpCustomerController.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; +import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; +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.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 客户") +@RestController +@RequestMapping("/erp/customer") +@Validated +public class ErpCustomerController { + + @Resource + private ErpCustomerService customerService; + + @PostMapping("/create") + @Operation(summary = "创建客户") + @PreAuthorize("@ss.hasPermission('erp:customer:create')") + public CommonResult createCustomer(@Valid @RequestBody ErpCustomerSaveReqVO createReqVO) { + return success(customerService.createCustomer(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新客户") + @PreAuthorize("@ss.hasPermission('erp:customer:update')") + public CommonResult updateCustomer(@Valid @RequestBody ErpCustomerSaveReqVO updateReqVO) { + customerService.updateCustomer(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除客户") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('erp: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('erp:customer:query')") + public CommonResult getCustomer(@RequestParam("id") Long id) { + ErpCustomerDO customer = customerService.getCustomer(id); + return success(BeanUtils.toBean(customer, ErpCustomerRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得客户分页") + @PreAuthorize("@ss.hasPermission('erp:customer:query')") + public CommonResult> getCustomerPage(@Valid ErpCustomerPageReqVO pageReqVO) { + PageResult pageResult = customerService.getCustomerPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, ErpCustomerRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得客户精简列表", description = "只包含被开启的客户,主要用于前端的下拉选项") + public CommonResult> getCustomerSimpleList() { + List list = customerService.getCustomerListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, customer -> new ErpCustomerRespVO().setId(customer.getId()).setName(customer.getName()))); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出客户 Excel") + @PreAuthorize("@ss.hasPermission('erp:customer:export')") + @OperateLog(type = EXPORT) + public void exportCustomerExcel(@Valid ErpCustomerPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = customerService.getCustomerPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "客户.xls", "数据", ErpCustomerRespVO.class, + BeanUtils.toBean(list, ErpCustomerRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java new file mode 100644 index 000000000..15d1fa84a --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java @@ -0,0 +1,165 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderItemDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; +import cn.iocoder.yudao.module.erp.service.sale.ErpSaleOrderService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import 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.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + + +@Tag(name = "管理后台 - ERP 销售订单") +@RestController +@RequestMapping("/erp/sale-order") +@Validated +public class ErpSaleOrderController { + + @Resource + private ErpSaleOrderService saleOrderService; + @Resource + private ErpStockService stockService; + @Resource + private ErpProductService productService; + @Resource + private ErpCustomerService customerService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建销售订单") + @PreAuthorize("@ss.hasPermission('erp:sale-out:create')") + public CommonResult createSaleOrder(@Valid @RequestBody ErpSaleOrderSaveReqVO createReqVO) { + return success(saleOrderService.createSaleOrder(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新销售订单") + @PreAuthorize("@ss.hasPermission('erp:sale-out:update')") + public CommonResult updateSaleOrder(@Valid @RequestBody ErpSaleOrderSaveReqVO updateReqVO) { + saleOrderService.updateSaleOrder(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新销售订单的状态") + @PreAuthorize("@ss.hasPermission('erp:sale-out:update-status')") + public CommonResult updateSaleOrderStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + saleOrderService.updateSaleOrderStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除销售订单") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:sale-out:delete')") + public CommonResult deleteSaleOrder(@RequestParam("ids") List ids) { + saleOrderService.deleteSaleOrder(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得销售订单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:sale-out:query')") + public CommonResult getSaleOrder(@RequestParam("id") Long id) { + ErpSaleOrderDO saleOrder = saleOrderService.getSaleOrder(id); + if (saleOrder == null) { + return success(null); + } + List saleOrderItemList = saleOrderService.getSaleOrderItemListByOrderId(id); + Map productMap = productService.getProductVOMap( + convertSet(saleOrderItemList, ErpSaleOrderItemDO::getProductId)); + return success(BeanUtils.toBean(saleOrder, ErpSaleOrderRespVO.class, saleOrderVO -> + saleOrderVO.setItems(BeanUtils.toBean(saleOrderItemList, ErpSaleOrderRespVO.Item.class, item -> { + BigDecimal stockCount = stockService.getStockCount(item.getProductId()); + item.setStockCount(stockCount != null ? stockCount : BigDecimal.ZERO); + MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())); + })))); + } + + @GetMapping("/page") + @Operation(summary = "获得销售订单分页") + @PreAuthorize("@ss.hasPermission('erp:sale-out:query')") + public CommonResult> getSaleOrderPage(@Valid ErpSaleOrderPageReqVO pageReqVO) { + PageResult pageResult = saleOrderService.getSaleOrderPage(pageReqVO); + return success(buildSaleOrderVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出销售订单 Excel") + @PreAuthorize("@ss.hasPermission('erp:sale-out:export')") + @OperateLog(type = EXPORT) + public void exportSaleOrderExcel(@Valid ErpSaleOrderPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildSaleOrderVOPageResult(saleOrderService.getSaleOrderPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "销售订单.xls", "数据", ErpSaleOrderRespVO.class, list); + } + + private PageResult buildSaleOrderVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 订单项 + List saleOrderItemList = saleOrderService.getSaleOrderItemListByOrderIds( + convertSet(pageResult.getList(), ErpSaleOrderDO::getId)); + Map> saleOrderItemMap = convertMultiMap(saleOrderItemList, ErpSaleOrderItemDO::getOrderId); + // 1.2 产品信息 + Map productMap = productService.getProductVOMap( + convertSet(saleOrderItemList, ErpSaleOrderItemDO::getProductId)); + // 1.3 客户信息 + Map customerMap = customerService.getCustomerMap( + convertSet(pageResult.getList(), ErpSaleOrderDO::getCustomerId)); + // 1.4 管理员信息 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), saleOrder -> Long.parseLong(saleOrder.getCreator()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpSaleOrderRespVO.class, saleOrder -> { + saleOrder.setItems(BeanUtils.toBean(saleOrderItemMap.get(saleOrder.getId()), ErpSaleOrderRespVO.Item.class, + item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); + saleOrder.setProductNames(CollUtil.join(saleOrder.getItems(), ",", ErpSaleOrderRespVO.Item::getProductName)); + MapUtils.findAndThen(customerMap, saleOrder.getCustomerId(), supplier -> saleOrder.setCustomerName(supplier.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(saleOrder.getCreator()), user -> saleOrder.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java new file mode 100644 index 000000000..cdf1196da --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java @@ -0,0 +1,165 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out.ErpSaleOutPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out.ErpSaleOutRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out.ErpSaleOutSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; +import cn.iocoder.yudao.module.erp.service.sale.ErpSaleOutService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import 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.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 销售出库") +@RestController +@RequestMapping("/erp/sale-out") +@Validated +public class ErpSaleOutController { + + @Resource + private ErpSaleOutService saleOutService; + @Resource + private ErpStockService stockService; + @Resource + private ErpProductService productService; + @Resource + private ErpCustomerService customerService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建销售出库") + @PreAuthorize("@ss.hasPermission('erp:sale-out:create')") + public CommonResult createSaleOut(@Valid @RequestBody ErpSaleOutSaveReqVO createReqVO) { + return success(saleOutService.createSaleOut(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新销售出库") + @PreAuthorize("@ss.hasPermission('erp:sale-out:update')") + public CommonResult updateSaleOut(@Valid @RequestBody ErpSaleOutSaveReqVO updateReqVO) { + saleOutService.updateSaleOut(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新销售出库的状态") + @PreAuthorize("@ss.hasPermission('erp:sale-out:update-status')") + public CommonResult updateSaleOutStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + saleOutService.updateSaleOutStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除销售出库") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:sale-out:delete')") + public CommonResult deleteSaleOut(@RequestParam("ids") List ids) { + saleOutService.deleteSaleOut(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得销售出库") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:sale-out:query')") + public CommonResult getSaleOut(@RequestParam("id") Long id) { + ErpSaleOutDO saleOut = saleOutService.getSaleOut(id); + if (saleOut == null) { + return success(null); + } + List saleOutItemList = saleOutService.getSaleOutItemListByOutId(id); + Map productMap = productService.getProductVOMap( + convertSet(saleOutItemList, ErpSaleOutItemDO::getProductId)); + return success(BeanUtils.toBean(saleOut, ErpSaleOutRespVO.class, saleOutVO -> + saleOutVO.setItems(BeanUtils.toBean(saleOutItemList, ErpSaleOutRespVO.Item.class, item -> { + ErpStockDO stock = stockService.getStock(item.getProductId(), item.getWarehouseId()); + item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO); + MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())); + })))); + } + + @GetMapping("/page") + @Operation(summary = "获得销售出库分页") + @PreAuthorize("@ss.hasPermission('erp:sale-out:query')") + public CommonResult> getSaleOutPage(@Valid ErpSaleOutPageReqVO pageReqVO) { + PageResult pageResult = saleOutService.getSaleOutPage(pageReqVO); + return success(buildSaleOutVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出销售出库 Excel") + @PreAuthorize("@ss.hasPermission('erp:sale-out:export')") + @OperateLog(type = EXPORT) + public void exportSaleOutExcel(@Valid ErpSaleOutPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildSaleOutVOPageResult(saleOutService.getSaleOutPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "销售出库.xls", "数据", ErpSaleOutRespVO.class, list); + } + + private PageResult buildSaleOutVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 出库项 + List saleOutItemList = saleOutService.getSaleOutItemListByOutIds( + convertSet(pageResult.getList(), ErpSaleOutDO::getId)); + Map> saleOutItemMap = convertMultiMap(saleOutItemList, ErpSaleOutItemDO::getOutId); + // 1.2 产品信息 + Map productMap = productService.getProductVOMap( + convertSet(saleOutItemList, ErpSaleOutItemDO::getProductId)); + // 1.3 客户信息 + Map customerMap = customerService.getCustomerMap( + convertSet(pageResult.getList(), ErpSaleOutDO::getCustomerId)); + // 1.4 管理员信息 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), stockOut -> Long.parseLong(stockOut.getCreator()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpSaleOutRespVO.class, saleOut -> { + saleOut.setItems(BeanUtils.toBean(saleOutItemMap.get(saleOut.getId()), ErpSaleOutRespVO.Item.class, + item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); + saleOut.setProductNames(CollUtil.join(saleOut.getItems(), ",", ErpSaleOutRespVO.Item::getProductName)); + MapUtils.findAndThen(customerMap, saleOut.getCustomerId(), supplier -> saleOut.setCustomerName(supplier.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(saleOut.getCreator()), user -> saleOut.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java new file mode 100644 index 000000000..d5dbffe52 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java @@ -0,0 +1,165 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns.ErpSaleReturnPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns.ErpSaleReturnRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns.ErpSaleReturnSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; +import cn.iocoder.yudao.module.erp.service.sale.ErpSaleReturnService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import 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.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 销售退货") +@RestController +@RequestMapping("/erp/sale-return") +@Validated +public class ErpSaleReturnController { + + @Resource + private ErpSaleReturnService saleReturnService; + @Resource + private ErpStockService stockService; + @Resource + private ErpProductService productService; + @Resource + private ErpCustomerService customerService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建销售退货") + @PreAuthorize("@ss.hasPermission('erp:sale-return:create')") + public CommonResult createSaleReturn(@Valid @RequestBody ErpSaleReturnSaveReqVO createReqVO) { + return success(saleReturnService.createSaleReturn(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新销售退货") + @PreAuthorize("@ss.hasPermission('erp:sale-return:update')") + public CommonResult updateSaleReturn(@Valid @RequestBody ErpSaleReturnSaveReqVO updateReqVO) { + saleReturnService.updateSaleReturn(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新销售退货的状态") + @PreAuthorize("@ss.hasPermission('erp:sale-return:update-status')") + public CommonResult updateSaleReturnStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + saleReturnService.updateSaleReturnStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除销售退货") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:sale-return:delete')") + public CommonResult deleteSaleReturn(@RequestParam("ids") List ids) { + saleReturnService.deleteSaleReturn(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得销售退货") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:sale-return:query')") + public CommonResult getSaleReturn(@RequestParam("id") Long id) { + ErpSaleReturnDO saleReturn = saleReturnService.getSaleReturn(id); + if (saleReturn == null) { + return success(null); + } + List saleReturnItemList = saleReturnService.getSaleReturnItemListByReturnId(id); + Map productMap = productService.getProductVOMap( + convertSet(saleReturnItemList, ErpSaleReturnItemDO::getProductId)); + return success(BeanUtils.toBean(saleReturn, ErpSaleReturnRespVO.class, saleReturnVO -> + saleReturnVO.setItems(BeanUtils.toBean(saleReturnItemList, ErpSaleReturnRespVO.Item.class, item -> { + ErpStockDO stock = stockService.getStock(item.getProductId(), item.getWarehouseId()); + item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO); + MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())); + })))); + } + + @GetMapping("/page") + @Operation(summary = "获得销售退货分页") + @PreAuthorize("@ss.hasPermission('erp:sale-return:query')") + public CommonResult> getSaleReturnPage(@Valid ErpSaleReturnPageReqVO pageReqVO) { + PageResult pageResult = saleReturnService.getSaleReturnPage(pageReqVO); + return success(buildSaleReturnVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出销售退货 Excel") + @PreAuthorize("@ss.hasPermission('erp:sale-return:export')") + @OperateLog(type = EXPORT) + public void exportSaleReturnExcel(@Valid ErpSaleReturnPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildSaleReturnVOPageResult(saleReturnService.getSaleReturnPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "销售退货.xls", "数据", ErpSaleReturnRespVO.class, list); + } + + private PageResult buildSaleReturnVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 退货项 + List saleReturnItemList = saleReturnService.getSaleReturnItemListByReturnIds( + convertSet(pageResult.getList(), ErpSaleReturnDO::getId)); + Map> saleReturnItemMap = convertMultiMap(saleReturnItemList, ErpSaleReturnItemDO::getReturnId); + // 1.2 产品信息 + Map productMap = productService.getProductVOMap( + convertSet(saleReturnItemList, ErpSaleReturnItemDO::getProductId)); + // 1.3 客户信息 + Map customerMap = customerService.getCustomerMap( + convertSet(pageResult.getList(), ErpSaleReturnDO::getCustomerId)); + // 1.4 管理员信息 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), saleReturn -> Long.parseLong(saleReturn.getCreator()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpSaleReturnRespVO.class, saleReturn -> { + saleReturn.setItems(BeanUtils.toBean(saleReturnItemMap.get(saleReturn.getId()), ErpSaleReturnRespVO.Item.class, + item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); + saleReturn.setProductNames(CollUtil.join(saleReturn.getItems(), ",", ErpSaleReturnRespVO.Item::getProductName)); + MapUtils.findAndThen(customerMap, saleReturn.getCustomerId(), supplier -> saleReturn.setCustomerName(supplier.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(saleReturn.getCreator()), user -> saleReturn.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerPageReqVO.java new file mode 100644 index 000000000..e790cb958 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerPageReqVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import java.math.BigDecimal; +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 = "管理后台 - ERP 客户分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpCustomerPageReqVO extends PageParam { + + @Schema(description = "客户名称", example = "张三") + private String name; + + @Schema(description = "手机号码", example = "15601691300") + private String mobile; + + @Schema(description = "联系电话", example = "15601691300") + private String telephone; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerRespVO.java new file mode 100644 index 000000000..f1a58a03d --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerRespVO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.util.*; +import java.math.BigDecimal; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; + +@Schema(description = "管理后台 - ERP 客户 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpCustomerRespVO { + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "27520") + @ExcelProperty("客户编号") + private Long id; + + @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + @ExcelProperty("客户名称") + private String name; + + @Schema(description = "联系人", example = "老王") + @ExcelProperty("联系人") + private String contact; + + @Schema(description = "手机号码", example = "15601691300") + @ExcelProperty("手机号码") + private String mobile; + + @Schema(description = "联系电话", example = "15601691300") + @ExcelProperty("联系电话") + private String telephone; + + @Schema(description = "电子邮箱", example = "7685323@qq.com") + @ExcelProperty("电子邮箱") + private String email; + + @Schema(description = "传真", example = "20 7123 4567") + @ExcelProperty("传真") + private String fax; + + @Schema(description = "备注", example = "你猜") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "开启状态", converter = DictConvert.class) + @DictFormat("common_status") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Integer status; + + @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty("排序") + private Integer sort; + + @Schema(description = "纳税人识别号", example = "91130803MA098BY05W") + @ExcelProperty("纳税人识别号") + private String taxNo; + + @Schema(description = "税率", example = "10") + @ExcelProperty("税率") + private BigDecimal taxPercent; + + @Schema(description = "开户行", example = "芋艿") + @ExcelProperty("开户行") + private String bankName; + + @Schema(description = "开户账号", example = "622908212277228617") + @ExcelProperty("开户账号") + private String bankAccount; + + @Schema(description = "开户地址", example = "兴业银行浦东支行") + @ExcelProperty("开户地址") + private String bankAddress; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerSaveReqVO.java new file mode 100644 index 000000000..bff15474b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerSaveReqVO.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +import javax.validation.constraints.*; +import java.math.BigDecimal; + +@Schema(description = "管理后台 - ERP 客户新增/修改 Request VO") +@Data +public class ErpCustomerSaveReqVO { + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "27520") + private Long id; + + @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + @NotEmpty(message = "客户名称不能为空") + private String name; + + @Schema(description = "联系人", example = "老王") + private String contact; + + @Schema(description = "手机号码", example = "15601691300") + private String mobile; + + @Schema(description = "联系电话", example = "15601691300") + private String telephone; + + @Schema(description = "电子邮箱", example = "7685323@qq.com") + private String email; + + @Schema(description = "传真", example = "20 7123 4567") + private String fax; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "开启状态不能为空") + private Integer status; + + @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @NotNull(message = "排序不能为空") + private Integer sort; + + @Schema(description = "纳税人识别号", example = "91130803MA098BY05W") + private String taxNo; + + @Schema(description = "税率", example = "10") + private BigDecimal taxPercent; + + @Schema(description = "开户行", example = "芋艿") + private String bankName; + + @Schema(description = "开户账号", example = "622908212277228617") + private String bankAccount; + + @Schema(description = "开户地址", example = "兴业银行浦东支行") + private String bankAddress; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java new file mode 100644 index 000000000..84d92fb67 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order; + +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 = "管理后台 - ERP 销售订单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpSaleOrderPageReqVO extends PageParam { + + /** + * 出库状态 - 无 + */ + public static final Integer OUT_STATUS_NONE = 0; + /** + * 出库状态 - 部分 + */ + public static final Integer OUT_STATUS_PART = 1; + /** + * 出库状态 - 全部 + */ + public static final Integer OUT_STATUS_ALL = 2; + + /** + * 退货状态 - 无 + */ + public static final Integer RETURN_STATUS_NONE = 0; + /** + * 退货状态 - 部分 + */ + public static final Integer RETURN_STATUS_PART = 1; + /** + * 退货状态 - 全部 + */ + public static final Integer RETURN_STATUS_ALL = 2; + + @Schema(description = "销售单编号", example = "XS001") + private String no; + + @Schema(description = "客户编号", example = "1724") + private Long customerId; + + @Schema(description = "下单时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] orderTime; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "销售状态", example = "2") + private Integer status; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "产品编号", example = "1") + private Long productId; + + @Schema(description = "出库状态", example = "2") + private Integer outStatus; + + @Schema(description = "退货状态", example = "2") + private Integer returnStatus; + + @Schema(description = "是否可出库", example = "true") + private Boolean outEnable; + + @Schema(description = "是否可退货", example = "true") + private Boolean returnEnable; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java new file mode 100644 index 000000000..370ea09db --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java @@ -0,0 +1,155 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 销售订单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpSaleOrderRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "销售单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + @ExcelProperty("销售单编号") + private String no; + + @Schema(description = "销售状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty("销售状态") + private Integer status; + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1724") + private Long customerId; + @Schema(description = "客户名称", example = "芋道") + @ExcelProperty("客户名称") + private String customerName; + + @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "311.89") + @ExcelProperty("结算账户编号") + private Long accountId; + + @Schema(description = "销售员编号", example = "1888") + private Long saleUserId; + + @Schema(description = "下单时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("下单时间") + private LocalDateTime orderTime; + + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") + @ExcelProperty("合计数量") + private BigDecimal totalCount; + @Schema(description = "最终合计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @ExcelProperty("最终合计价格") + private BigDecimal totalPrice; + + @Schema(description = "合计产品价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalProductPrice; + + @Schema(description = "合计税额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalTaxPrice; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal discountPrice; + + @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal depositPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + @ExcelProperty("附件地址") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建人", example = "芋道") + private String creator; + @Schema(description = "创建人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "订单项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("产品信息") + private String productNames; + + // ========== 销售出库 ========== + + @Schema(description = "销售出库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal outCount; + + // ========== 销售退货(出库)) ========== + + @Schema(description = "销售退货数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal returnCount; + + @Data + public static class Item { + + @Schema(description = "订单项编号", example = "11756") + private Long id; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "税额,单位:元", example = "100.00") + private BigDecimal taxPrice; + + @Schema(description = "备注", example = "随便") + private String remark; + + // ========== 销售出库 ========== + + @Schema(description = "销售出库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal outCount; + + // ========== 销售退货(入库)) ========== + + @Schema(description = "销售退货数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal returnCount; + + // ========== 关联字段 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") + private String productBarCode; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") + private String productUnitName; + + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal stockCount; // 该字段仅仅在“详情”和“编辑”时使用 + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java new file mode 100644 index 000000000..f743a841a --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 销售订单新增/修改 Request VO") +@Data +public class ErpSaleOrderSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + private Long id; + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1724") + @NotNull(message = "客户编号不能为空") + private Long customerId; + + @Schema(description = "下单时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "下单时间不能为空") + private LocalDateTime orderTime; + + @Schema(description = "销售员编号", example = "1888") + private Long saleUserId; + + @Schema(description = "结算账户编号", example = "31189") + private Long accountId; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "定金金额,单位:元", example = "7127") + private BigDecimal depositPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "订单清单列表") + private List items; + + @Data + public static class Item { + + @Schema(description = "订单项编号", example = "11756") + private Long id; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品编号不能为空") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品单位单位不能为空") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutPageReqVO.java new file mode 100644 index 000000000..5afeeea84 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutPageReqVO.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out; + +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 = "管理后台 - ERP 销售出库分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpSaleOutPageReqVO extends PageParam { + + public static final Integer RECEIPT_STATUS_NONE = 0; + public static final Integer RECEIPT_STATUS_PART = 1; + public static final Integer RECEIPT_STATUS_ALL = 2; + + @Schema(description = "销售单编号", example = "XS001") + private String no; + + @Schema(description = "客户编号", example = "1724") + private Long customerId; + + @Schema(description = "出库时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] outTime; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "出库状态", example = "2") + private Integer status; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "产品编号", example = "1") + private Long productId; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "结算账号编号", example = "1") + private Long accountId; + + @Schema(description = "收款状态", example = "1") + private Integer receiptStatus; + + @Schema(description = "是否可收款", example = "true") + private Boolean receiptEnable; // 对应 receiptStatus = [0, 1] + + @Schema(description = "销售单号", example = "1") + private String orderNo; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java new file mode 100644 index 000000000..f852c411c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java @@ -0,0 +1,148 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 销售出库 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpSaleOutRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "出库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + @ExcelProperty("出库单编号") + private String no; + + @Schema(description = "出库状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty("出库状态") + private Integer status; + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1724") + private Long customerId; + @Schema(description = "客户名称", example = "芋道") + @ExcelProperty("客户名称") + private String customerName; + + @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "311.89") + @ExcelProperty("结算账户编号") + private Long accountId; + + @Schema(description = "出库员编号", example = "1888") + private Long saleUserId; + + @Schema(description = "出库时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("出库时间") + private LocalDateTime outTime; + + @Schema(description = "销售订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + private Long orderId; + @Schema(description = "销售订单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + private String orderNo; + + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") + @ExcelProperty("合计数量") + private BigDecimal totalCount; + @Schema(description = "最终合计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @ExcelProperty("最终合计价格") + private BigDecimal totalPrice; + @Schema(description = "已收款金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal receiptPrice; + + @Schema(description = "合计产品价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalProductPrice; + + @Schema(description = "合计税额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalTaxPrice; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal discountPrice; + + @Schema(description = "其它金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal otherPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + @ExcelProperty("附件地址") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建人", example = "芋道") + private String creator; + @Schema(description = "创建人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "出库项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("产品信息") + private String productNames; + + @Data + public static class Item { + + @Schema(description = "出库项编号", example = "11756") + private Long id; + + @Schema(description = "销售订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private Long orderItemId; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "税额,单位:元", example = "100.00") + private BigDecimal taxPrice; + + @Schema(description = "备注", example = "随便") + private String remark; + + // ========== 关联字段 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") + private String productBarCode; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") + private String productUnitName; + + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal stockCount; // 该字段仅仅在“详情”和“编辑”时使用 + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutSaveReqVO.java new file mode 100644 index 000000000..61a87f6f4 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutSaveReqVO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 销售出库新增/修改 Request VO") +@Data +public class ErpSaleOutSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + private Long id; + + @Schema(description = "结算账户编号", example = "31189") + private Long accountId; + + @Schema(description = "销售员编号", example = "1888") + private Long saleUserId; + + @Schema(description = "出库时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出库时间不能为空") + private LocalDateTime outTime; + + @Schema(description = "销售订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + @NotNull(message = "销售订单编号不能为空") + private Long orderId; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "其它金额,单位:元", example = "7127") + private BigDecimal otherPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "出库清单列表") + private List items; + + @Data + public static class Item { + + @Schema(description = "出库项编号", example = "11756") + private Long id; + + @Schema(description = "销售订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @NotNull(message = "销售订单项编号不能为空") + private Long orderItemId; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "仓库编号不能为空") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品编号不能为空") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品单位单位不能为空") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnPageReqVO.java new file mode 100644 index 000000000..a9be73beb --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnPageReqVO.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns; + +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 = "管理后台 - ERP 销售退货分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpSaleReturnPageReqVO extends PageParam { + + public static final Integer REFUND_STATUS_NONE = 0; + public static final Integer REFUND_STATUS_PART = 1; + public static final Integer REFUND_STATUS_ALL = 2; + + @Schema(description = "销售单编号", example = "XS001") + private String no; + + @Schema(description = "客户编号", example = "1724") + private Long customerId; + + @Schema(description = "退货时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] returnTime; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "退货状态", example = "2") + private Integer status; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "产品编号", example = "1") + private Long productId; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "结算账号编号", example = "1") + private Long accountId; + + @Schema(description = "销售单号", example = "1") + private String orderNo; + + @Schema(description = "退款状态", example = "1") + private Integer refundStatus; + + @Schema(description = "是否可退款", example = "true") + private Boolean refundEnable; // 对应 refundStatus = [0, 1] + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java new file mode 100644 index 000000000..2ca3384fa --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java @@ -0,0 +1,148 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import javax.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 销售退货 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpSaleReturnRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "退货单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + @ExcelProperty("退货单编号") + private String no; + + @Schema(description = "退货状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty("退货状态") + private Integer status; + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1724") + private Long customerId; + @Schema(description = "客户名称", example = "芋道") + @ExcelProperty("客户名称") + private String customerName; + + @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "311.89") + @ExcelProperty("结算账户编号") + private Long accountId; + + @Schema(description = "退货员编号", example = "1888") + private Long saleUserId; + + @Schema(description = "退货时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("退货时间") + private LocalDateTime returnTime; + + @Schema(description = "销售订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + private Long orderId; + @Schema(description = "销售订单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + private String orderNo; + + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") + @ExcelProperty("合计数量") + private BigDecimal totalCount; + @Schema(description = "最终合计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @ExcelProperty("最终合计价格") + private BigDecimal totalPrice; + @Schema(description = "已退款金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal refundPrice; + + @Schema(description = "合计产品价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalProductPrice; + + @Schema(description = "合计税额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalTaxPrice; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal discountPrice; + + @Schema(description = "其它金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal otherPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + @ExcelProperty("附件地址") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建人", example = "芋道") + private String creator; + @Schema(description = "创建人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "退货项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("产品信息") + private String productNames; + + @Data + public static class Item { + + @Schema(description = "退货项编号", example = "11756") + private Long id; + + @Schema(description = "销售订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private Long orderItemId; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "税额,单位:元", example = "100.00") + private BigDecimal taxPrice; + + @Schema(description = "备注", example = "随便") + private String remark; + + // ========== 关联字段 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") + private String productBarCode; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") + private String productUnitName; + + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal stockCount; // 该字段仅仅在“详情”和“编辑”时使用 + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnSaveReqVO.java new file mode 100644 index 000000000..44eb0df34 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnSaveReqVO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 销售退货新增/修改 Request VO") +@Data +public class ErpSaleReturnSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + private Long id; + + @Schema(description = "结算账户编号", example = "31189") + private Long accountId; + + @Schema(description = "销售员编号", example = "1888") + private Long saleUserId; + + @Schema(description = "退货时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "退货时间不能为空") + private LocalDateTime returnTime; + + @Schema(description = "销售订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + @NotNull(message = "销售订单编号不能为空") + private Long orderId; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "其它金额,单位:元", example = "7127") + private BigDecimal otherPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "退货清单列表") + private List items; + + @Data + public static class Item { + + @Schema(description = "退货项编号", example = "11756") + private Long id; + + @Schema(description = "销售订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @NotNull(message = "销售订单项编号不能为空") + private Long orderItemId; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "仓库编号不能为空") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品编号不能为空") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品单位单位不能为空") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java new file mode 100644 index 000000000..6d907cef0 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java @@ -0,0 +1,149 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckItemDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockCheckService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import 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 java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 库存调拨单") +@RestController +@RequestMapping("/erp/stock-check") +@Validated +public class ErpStockCheckController { + + @Resource + private ErpStockCheckService stockCheckService; + @Resource + private ErpProductService productService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建库存调拨单") + @PreAuthorize("@ss.hasPermission('erp:stock-check:create')") + public CommonResult createStockCheck(@Valid @RequestBody ErpStockCheckSaveReqVO createReqVO) { + return success(stockCheckService.createStockCheck(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新库存调拨单") + @PreAuthorize("@ss.hasPermission('erp:stock-check:update')") + public CommonResult updateStockCheck(@Valid @RequestBody ErpStockCheckSaveReqVO updateReqVO) { + stockCheckService.updateStockCheck(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新库存调拨单的状态") + @PreAuthorize("@ss.hasPermission('erp:stock-check:update-status')") + public CommonResult updateStockCheckStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + stockCheckService.updateStockCheckStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除库存调拨单") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:stock-check:delete')") + public CommonResult deleteStockCheck(@RequestParam("ids") List ids) { + stockCheckService.deleteStockCheck(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得库存调拨单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:stock-check:query')") + public CommonResult getStockCheck(@RequestParam("id") Long id) { + ErpStockCheckDO stockCheck = stockCheckService.getStockCheck(id); + if (stockCheck == null) { + return success(null); + } + List stockCheckItemList = stockCheckService.getStockCheckItemListByCheckId(id); + Map productMap = productService.getProductVOMap( + convertSet(stockCheckItemList, ErpStockCheckItemDO::getProductId)); + return success(BeanUtils.toBean(stockCheck, ErpStockCheckRespVO.class, stockCheckVO -> + stockCheckVO.setItems(BeanUtils.toBean(stockCheckItemList, ErpStockCheckRespVO.Item.class, item -> + MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))))); + } + + @GetMapping("/page") + @Operation(summary = "获得库存调拨单分页") + @PreAuthorize("@ss.hasPermission('erp:stock-check:query')") + public CommonResult> getStockCheckPage(@Valid ErpStockCheckPageReqVO pageReqVO) { + PageResult pageResult = stockCheckService.getStockCheckPage(pageReqVO); + return success(buildStockCheckVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出库存调拨单 Excel") + @PreAuthorize("@ss.hasPermission('erp:stock-check:export')") + @OperateLog(type = EXPORT) + public void exportStockCheckExcel(@Valid ErpStockCheckPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildStockCheckVOPageResult(stockCheckService.getStockCheckPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "库存调拨单.xls", "数据", ErpStockCheckRespVO.class, list); + } + + private PageResult buildStockCheckVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 盘点项 + List stockCheckItemList = stockCheckService.getStockCheckItemListByCheckIds( + convertSet(pageResult.getList(), ErpStockCheckDO::getId)); + Map> stockCheckItemMap = convertMultiMap(stockCheckItemList, ErpStockCheckItemDO::getCheckId); + // 1.2 产品信息 + Map productMap = productService.getProductVOMap( + convertSet(stockCheckItemList, ErpStockCheckItemDO::getProductId)); + // 1.3 管理员信息 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), stockCheck -> Long.parseLong(stockCheck.getCreator()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpStockCheckRespVO.class, stockCheck -> { + stockCheck.setItems(BeanUtils.toBean(stockCheckItemMap.get(stockCheck.getId()), ErpStockCheckRespVO.Item.class, + item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); + stockCheck.setProductNames(CollUtil.join(stockCheck.getItems(), ",", ErpStockCheckRespVO.Item::getProductName)); + MapUtils.findAndThen(userMap, Long.parseLong(stockCheck.getCreator()), user -> stockCheck.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java new file mode 100644 index 000000000..0ef9b0205 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java @@ -0,0 +1,112 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockRespVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; +import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.IOException; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 产品库存") +@RestController +@RequestMapping("/erp/stock") +@Validated +public class ErpStockController { + + @Resource + private ErpStockService stockService; + @Resource + private ErpProductService productService; + @Resource + private ErpWarehouseService warehouseService; + + @GetMapping("/get") + @Operation(summary = "获得产品库存") + @Parameters({ + @Parameter(name = "id", description = "编号", example = "1"), // 方案一:传递 id + @Parameter(name = "productId", description = "产品编号", example = "10"), // 方案二:传递 productId + warehouseId + @Parameter(name = "warehouseId", description = "仓库编号", example = "2") + }) + @PreAuthorize("@ss.hasPermission('erp:stock:query')") + public CommonResult getStock(@RequestParam(value = "id", required = false) Long id, + @RequestParam(value = "productId", required = false) Long productId, + @RequestParam(value = "warehouseId", required = false) Long warehouseId) { + ErpStockDO stock = id != null ? stockService.getStock(id) : stockService.getStock(productId, warehouseId); + return success(BeanUtils.toBean(stock, ErpStockRespVO.class)); + } + + @GetMapping("/get-count") + @Operation(summary = "获得产品库存数量") + @Parameter(name = "productId", description = "产品编号", example = "10") + public CommonResult getStockCount(@RequestParam("productId") Long productId) { + return success(stockService.getStockCount(productId)); + } + + @GetMapping("/page") + @Operation(summary = "获得产品库存分页") + @PreAuthorize("@ss.hasPermission('erp:stock:query')") + public CommonResult> getStockPage(@Valid ErpStockPageReqVO pageReqVO) { + PageResult pageResult = stockService.getStockPage(pageReqVO); + return success(buildStockVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出产品库存 Excel") + @PreAuthorize("@ss.hasPermission('erp:stock:export')") + @OperateLog(type = EXPORT) + public void exportStockExcel(@Valid ErpStockPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildStockVOPageResult(stockService.getStockPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "产品库存.xls", "数据", ErpStockRespVO.class, list); + } + + private PageResult buildStockVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + Map productMap = productService.getProductVOMap( + convertSet(pageResult.getList(), ErpStockDO::getProductId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(pageResult.getList(), ErpStockDO::getWarehouseId)); + return BeanUtils.toBean(pageResult, ErpStockRespVO.class, stock -> { + MapUtils.findAndThen(productMap, stock.getProductId(), product -> stock.setProductName(product.getName()) + .setCategoryName(product.getCategoryName()).setUnitName(product.getUnitName())); + MapUtils.findAndThen(warehouseMap, stock.getWarehouseId(), warehouse -> stock.setWarehouseName(warehouse.getName())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java new file mode 100644 index 000000000..4333c134c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java @@ -0,0 +1,165 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockInService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import 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.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 其它入库单") +@RestController +@RequestMapping("/erp/stock-in") +@Validated +public class ErpStockInController { + + @Resource + private ErpStockInService stockInService; + @Resource + private ErpStockService stockService; + @Resource + private ErpProductService productService; + @Resource + private ErpSupplierService supplierService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建其它入库单") + @PreAuthorize("@ss.hasPermission('erp:stock-in:create')") + public CommonResult createStockIn(@Valid @RequestBody ErpStockInSaveReqVO createReqVO) { + return success(stockInService.createStockIn(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新其它入库单") + @PreAuthorize("@ss.hasPermission('erp:stock-in:update')") + public CommonResult updateStockIn(@Valid @RequestBody ErpStockInSaveReqVO updateReqVO) { + stockInService.updateStockIn(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新其它入库单的状态") + @PreAuthorize("@ss.hasPermission('erp:stock-in:update-status')") + public CommonResult updateStockInStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + stockInService.updateStockInStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除其它入库单") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:stock-in:delete')") + public CommonResult deleteStockIn(@RequestParam("ids") List ids) { + stockInService.deleteStockIn(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得其它入库单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:stock-in:query')") + public CommonResult getStockIn(@RequestParam("id") Long id) { + ErpStockInDO stockIn = stockInService.getStockIn(id); + if (stockIn == null) { + return success(null); + } + List stockInItemList = stockInService.getStockInItemListByInId(id); + Map productMap = productService.getProductVOMap( + convertSet(stockInItemList, ErpStockInItemDO::getProductId)); + return success(BeanUtils.toBean(stockIn, ErpStockInRespVO.class, stockInVO -> + stockInVO.setItems(BeanUtils.toBean(stockInItemList, ErpStockInRespVO.Item.class, item -> { + ErpStockDO stock = stockService.getStock(item.getProductId(), item.getWarehouseId()); + item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO); + MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())); + })))); + } + + @GetMapping("/page") + @Operation(summary = "获得其它入库单分页") + @PreAuthorize("@ss.hasPermission('erp:stock-in:query')") + public CommonResult> getStockInPage(@Valid ErpStockInPageReqVO pageReqVO) { + PageResult pageResult = stockInService.getStockInPage(pageReqVO); + return success(buildStockInVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出其它入库单 Excel") + @PreAuthorize("@ss.hasPermission('erp:stock-in:export')") + @OperateLog(type = EXPORT) + public void exportStockInExcel(@Valid ErpStockInPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildStockInVOPageResult(stockInService.getStockInPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "其它入库单.xls", "数据", ErpStockInRespVO.class, list); + } + + private PageResult buildStockInVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 入库项 + List stockInItemList = stockInService.getStockInItemListByInIds( + convertSet(pageResult.getList(), ErpStockInDO::getId)); + Map> stockInItemMap = convertMultiMap(stockInItemList, ErpStockInItemDO::getInId); + // 1.2 产品信息 + Map productMap = productService.getProductVOMap( + convertSet(stockInItemList, ErpStockInItemDO::getProductId)); + // 1.3 供应商信息 + Map supplierMap = supplierService.getSupplierMap( + convertSet(pageResult.getList(), ErpStockInDO::getSupplierId)); + // 1.4 管理员信息 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), stockIn -> Long.parseLong(stockIn.getCreator()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpStockInRespVO.class, stockIn -> { + stockIn.setItems(BeanUtils.toBean(stockInItemMap.get(stockIn.getId()), ErpStockInRespVO.Item.class, + item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); + stockIn.setProductNames(CollUtil.join(stockIn.getItems(), ",", ErpStockInRespVO.Item::getProductName)); + MapUtils.findAndThen(supplierMap, stockIn.getSupplierId(), supplier -> stockIn.setSupplierName(supplier.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(stockIn.getCreator()), user -> stockIn.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java new file mode 100644 index 000000000..afe0505ae --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java @@ -0,0 +1,160 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMovePageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveItemDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockMoveService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import 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.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 库存调拨单") +@RestController +@RequestMapping("/erp/stock-move") +@Validated +public class ErpStockMoveController { + + @Resource + private ErpStockMoveService stockMoveService; + @Resource + private ErpStockService stockService; + @Resource + private ErpProductService productService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建库存调拨单") + @PreAuthorize("@ss.hasPermission('erp:stock-move:create')") + public CommonResult createStockMove(@Valid @RequestBody ErpStockMoveSaveReqVO createReqVO) { + return success(stockMoveService.createStockMove(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新库存调拨单") + @PreAuthorize("@ss.hasPermission('erp:stock-move:update')") + public CommonResult updateStockMove(@Valid @RequestBody ErpStockMoveSaveReqVO updateReqVO) { + stockMoveService.updateStockMove(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新库存调拨单的状态") + @PreAuthorize("@ss.hasPermission('erp:stock-move:update-status')") + public CommonResult updateStockMoveStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + stockMoveService.updateStockMoveStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除库存调拨单") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:stock-move:delete')") + public CommonResult deleteStockMove(@RequestParam("ids") List ids) { + stockMoveService.deleteStockMove(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得库存调拨单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:stock-move:query')") + public CommonResult getStockMove(@RequestParam("id") Long id) { + ErpStockMoveDO stockMove = stockMoveService.getStockMove(id); + if (stockMove == null) { + return success(null); + } + List stockMoveItemList = stockMoveService.getStockMoveItemListByMoveId(id); + Map productMap = productService.getProductVOMap( + convertSet(stockMoveItemList, ErpStockMoveItemDO::getProductId)); + return success(BeanUtils.toBean(stockMove, ErpStockMoveRespVO.class, stockMoveVO -> + stockMoveVO.setItems(BeanUtils.toBean(stockMoveItemList, ErpStockMoveRespVO.Item.class, item -> { + ErpStockDO stock = stockService.getStock(item.getProductId(), item.getFromWarehouseId()); + item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO); + MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())); + })))); + } + + @GetMapping("/page") + @Operation(summary = "获得库存调拨单分页") + @PreAuthorize("@ss.hasPermission('erp:stock-move:query')") + public CommonResult> getStockMovePage(@Valid ErpStockMovePageReqVO pageReqVO) { + PageResult pageResult = stockMoveService.getStockMovePage(pageReqVO); + return success(buildStockMoveVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出库存调拨单 Excel") + @PreAuthorize("@ss.hasPermission('erp:stock-move:export')") + @OperateLog(type = EXPORT) + public void exportStockMoveExcel(@Valid ErpStockMovePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildStockMoveVOPageResult(stockMoveService.getStockMovePage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "库存调拨单.xls", "数据", ErpStockMoveRespVO.class, list); + } + + private PageResult buildStockMoveVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 调拨项 + List stockMoveItemList = stockMoveService.getStockMoveItemListByMoveIds( + convertSet(pageResult.getList(), ErpStockMoveDO::getId)); + Map> stockMoveItemMap = convertMultiMap(stockMoveItemList, ErpStockMoveItemDO::getMoveId); + // 1.2 产品信息 + Map productMap = productService.getProductVOMap( + convertSet(stockMoveItemList, ErpStockMoveItemDO::getProductId)); + // 1.3 TODO 芋艿:搞仓库信息 + // 1.4 管理员信息 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), stockMove -> Long.parseLong(stockMove.getCreator()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpStockMoveRespVO.class, stockMove -> { + stockMove.setItems(BeanUtils.toBean(stockMoveItemMap.get(stockMove.getId()), ErpStockMoveRespVO.Item.class, + item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); + stockMove.setProductNames(CollUtil.join(stockMove.getItems(), ",", ErpStockMoveRespVO.Item::getProductName)); + // TODO 芋艿: +// MapUtils.findAndThen(customerMap, stockMove.getCustomerId(), supplier -> stockMove.setCustomerName(supplier.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(stockMove.getCreator()), user -> stockMove.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java new file mode 100644 index 000000000..f55d37e5e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java @@ -0,0 +1,165 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockOutService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import 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.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 其它出库单") +@RestController +@RequestMapping("/erp/stock-out") +@Validated +public class ErpStockOutController { + + @Resource + private ErpStockOutService stockOutService; + @Resource + private ErpStockService stockService; + @Resource + private ErpProductService productService; + @Resource + private ErpCustomerService customerService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建其它出库单") + @PreAuthorize("@ss.hasPermission('erp:stock-out:create')") + public CommonResult createStockOut(@Valid @RequestBody ErpStockOutSaveReqVO createReqVO) { + return success(stockOutService.createStockOut(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新其它出库单") + @PreAuthorize("@ss.hasPermission('erp:stock-out:update')") + public CommonResult updateStockOut(@Valid @RequestBody ErpStockOutSaveReqVO updateReqVO) { + stockOutService.updateStockOut(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新其它出库单的状态") + @PreAuthorize("@ss.hasPermission('erp:stock-out:update-status')") + public CommonResult updateStockOutStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + stockOutService.updateStockOutStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除其它出库单") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:stock-out:delete')") + public CommonResult deleteStockOut(@RequestParam("ids") List ids) { + stockOutService.deleteStockOut(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得其它出库单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:stock-out:query')") + public CommonResult getStockOut(@RequestParam("id") Long id) { + ErpStockOutDO stockOut = stockOutService.getStockOut(id); + if (stockOut == null) { + return success(null); + } + List stockOutItemList = stockOutService.getStockOutItemListByOutId(id); + Map productMap = productService.getProductVOMap( + convertSet(stockOutItemList, ErpStockOutItemDO::getProductId)); + return success(BeanUtils.toBean(stockOut, ErpStockOutRespVO.class, stockOutVO -> + stockOutVO.setItems(BeanUtils.toBean(stockOutItemList, ErpStockOutRespVO.Item.class, item -> { + ErpStockDO stock = stockService.getStock(item.getProductId(), item.getWarehouseId()); + item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO); + MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())); + })))); + } + + @GetMapping("/page") + @Operation(summary = "获得其它出库单分页") + @PreAuthorize("@ss.hasPermission('erp:stock-out:query')") + public CommonResult> getStockOutPage(@Valid ErpStockOutPageReqVO pageReqVO) { + PageResult pageResult = stockOutService.getStockOutPage(pageReqVO); + return success(buildStockOutVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出其它出库单 Excel") + @PreAuthorize("@ss.hasPermission('erp:stock-out:export')") + @OperateLog(type = EXPORT) + public void exportStockOutExcel(@Valid ErpStockOutPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildStockOutVOPageResult(stockOutService.getStockOutPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "其它出库单.xls", "数据", ErpStockOutRespVO.class, list); + } + + private PageResult buildStockOutVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 出库项 + List stockOutItemList = stockOutService.getStockOutItemListByOutIds( + convertSet(pageResult.getList(), ErpStockOutDO::getId)); + Map> stockOutItemMap = convertMultiMap(stockOutItemList, ErpStockOutItemDO::getOutId); + // 1.2 产品信息 + Map productMap = productService.getProductVOMap( + convertSet(stockOutItemList, ErpStockOutItemDO::getProductId)); + // 1.3 客户信息 + Map customerMap = customerService.getCustomerMap( + convertSet(pageResult.getList(), ErpStockOutDO::getCustomerId)); + // 1.4 管理员信息 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), stockOut -> Long.parseLong(stockOut.getCreator()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpStockOutRespVO.class, stockOut -> { + stockOut.setItems(BeanUtils.toBean(stockOutItemMap.get(stockOut.getId()), ErpStockOutRespVO.Item.class, + item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); + stockOut.setProductNames(CollUtil.join(stockOut.getItems(), ",", ErpStockOutRespVO.Item::getProductName)); + MapUtils.findAndThen(customerMap, stockOut.getCustomerId(), supplier -> stockOut.setCustomerName(supplier.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(stockOut.getCreator()), user -> stockOut.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java new file mode 100644 index 000000000..0ca65536a --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java @@ -0,0 +1,105 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record.ErpStockRecordPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record.ErpStockRecordRespVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockRecordService; +import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 产品库存明细") +@RestController +@RequestMapping("/erp/stock-record") +@Validated +public class ErpStockRecordController { + + @Resource + private ErpStockRecordService stockRecordService; + @Resource + private ErpProductService productService; + @Resource + private ErpWarehouseService warehouseService; + + @Resource + private AdminUserApi adminUserApi; + + @GetMapping("/get") + @Operation(summary = "获得产品库存明细") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:stock-record:query')") + public CommonResult getStockRecord(@RequestParam("id") Long id) { + ErpStockRecordDO stockRecord = stockRecordService.getStockRecord(id); + return success(BeanUtils.toBean(stockRecord, ErpStockRecordRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得产品库存明细分页") + @PreAuthorize("@ss.hasPermission('erp:stock-record:query')") + public CommonResult> getStockRecordPage(@Valid ErpStockRecordPageReqVO pageReqVO) { + PageResult pageResult = stockRecordService.getStockRecordPage(pageReqVO); + return success(buildStockRecrodVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出产品库存明细 Excel") + @PreAuthorize("@ss.hasPermission('erp:stock-record:export')") + @OperateLog(type = EXPORT) + public void exportStockRecordExcel(@Valid ErpStockRecordPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildStockRecrodVOPageResult(stockRecordService.getStockRecordPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "产品库存明细.xls", "数据", ErpStockRecordRespVO.class, list); + } + + private PageResult buildStockRecrodVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + Map productMap = productService.getProductVOMap( + convertSet(pageResult.getList(), ErpStockRecordDO::getProductId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(pageResult.getList(), ErpStockRecordDO::getWarehouseId)); + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), record -> Long.parseLong(record.getCreator()))); + return BeanUtils.toBean(pageResult, ErpStockRecordRespVO.class, stock -> { + MapUtils.findAndThen(productMap, stock.getProductId(), product -> stock.setProductName(product.getName()) + .setCategoryName(product.getCategoryName()).setUnitName(product.getUnitName())); + MapUtils.findAndThen(warehouseMap, stock.getWarehouseId(), warehouse -> stock.setWarehouseName(warehouse.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(stock.getCreator()), user -> stock.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java new file mode 100644 index 000000000..c9a3a8165 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java @@ -0,0 +1,116 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.ErpWarehouseSaveReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehousePageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseRespVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import 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.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 仓库") +@RestController +@RequestMapping("/erp/warehouse") +@Validated +public class ErpWarehouseController { + + @Resource + private ErpWarehouseService warehouseService; + + @PostMapping("/create") + @Operation(summary = "创建仓库") + @PreAuthorize("@ss.hasPermission('erp:warehouse:create')") + public CommonResult createWarehouse(@Valid @RequestBody ErpWarehouseSaveReqVO createReqVO) { + return success(warehouseService.createWarehouse(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新仓库") + @PreAuthorize("@ss.hasPermission('erp:warehouse:update')") + public CommonResult updateWarehouse(@Valid @RequestBody ErpWarehouseSaveReqVO updateReqVO) { + warehouseService.updateWarehouse(updateReqVO); + return success(true); + } + + @PutMapping("/update-default-status") + @Operation(summary = "更新仓库默认状态") + @Parameters({ + @Parameter(name = "id", description = "编号", required = true), + @Parameter(name = "status", description = "状态", required = true) + }) + public CommonResult updateWarehouseDefaultStatus(@RequestParam("id") Long id, + @RequestParam("defaultStatus") Boolean defaultStatus) { + warehouseService.updateWarehouseDefaultStatus(id, defaultStatus); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除仓库") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('erp:warehouse:delete')") + public CommonResult deleteWarehouse(@RequestParam("id") Long id) { + warehouseService.deleteWarehouse(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得仓库") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:warehouse:query')") + public CommonResult getWarehouse(@RequestParam("id") Long id) { + ErpWarehouseDO warehouse = warehouseService.getWarehouse(id); + return success(BeanUtils.toBean(warehouse, ErpWarehouseRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得仓库分页") + @PreAuthorize("@ss.hasPermission('erp:warehouse:query')") + public CommonResult> getWarehousePage(@Valid ErpWarehousePageReqVO pageReqVO) { + PageResult pageResult = warehouseService.getWarehousePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, ErpWarehouseRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得仓库精简列表", description = "只包含被开启的仓库,主要用于前端的下拉选项") + public CommonResult> getWarehouseSimpleList() { + List list = warehouseService.getWarehouseListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, warehouse -> new ErpWarehouseRespVO().setId(warehouse.getId()) + .setName(warehouse.getName()).setDefaultStatus(warehouse.getDefaultStatus()))); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出仓库 Excel") + @PreAuthorize("@ss.hasPermission('erp:warehouse:export')") + @OperateLog(type = EXPORT) + public void exportWarehouseExcel(@Valid ErpWarehousePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = warehouseService.getWarehousePage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "仓库.xls", "数据", ErpWarehouseRespVO.class, + BeanUtils.toBean(list, ErpWarehouseRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckPageReqVO.java new file mode 100644 index 000000000..2bae14c1e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckPageReqVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +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 = "管理后台 - ERP 库存盘点单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpStockCheckPageReqVO extends PageParam { + + @Schema(description = "盘点单号", example = "S123") + private String no; + + @Schema(description = "仓库编号", example = "3113") + private Long warehouseId; + + @Schema(description = "盘点时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] checkTime; + + @Schema(description = "状态", example = "10") + @InEnum(ErpAuditStatus.class) + private Integer status; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "产品编号", example = "1") + private Long productId; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java new file mode 100644 index 000000000..88b75bb9c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java @@ -0,0 +1,111 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import javax.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.module.erp.enums.DictTypeConstants.AUDIT_STATUS; + +@Schema(description = "管理后台 - ERP 库存盘点单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpStockCheckRespVO { + + @Schema(description = "盘点编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @ExcelProperty("盘点编号") + private Long id; + + @Schema(description = "盘点单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "S123") + @ExcelProperty("盘点单号") + private String no; + + @Schema(description = "盘点时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("盘点时间") + private LocalDateTime checkTime; + + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") + @ExcelProperty("合计数量") + private BigDecimal totalCount; + + @Schema(description = "合计金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @ExcelProperty("合计金额") + private BigDecimal totalPrice; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(AUDIT_STATUS) + private Integer status; + + @Schema(description = "备注", example = "随便") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") + private String fileUrl; + + @Schema(description = "创建人", example = "芋道") + private String creator; + @Schema(description = "创建人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "盘点项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("产品信息") + private String productNames; + + @Data + public static class Item { + + @Schema(description = "盘点项编号", example = "11756") + private Long id; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productId; + + @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "账面数量(当前库存)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "账面数量不能为空") + private BigDecimal stockCount; + + @Schema(description = "实际数量(实际库存)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "实际数量不能为空") + private BigDecimal actualCount; + + @Schema(description = "盈亏数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "盈亏数量不能为空") + private BigDecimal count; + + @Schema(description = "备注", example = "随便") + private String remark; + + // ========== 关联字段 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") + private String productBarCode; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") + private String productUnitName; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckSaveReqVO.java new file mode 100644 index 000000000..80e126a28 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckSaveReqVO.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 其它出库单新增/修改 Request VO") +@Data +public class ErpStockCheckSaveReqVO { + + @Schema(description = "出库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private Long id; + + @Schema(description = "出库时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出库时间不能为空") + private LocalDateTime checkTime; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") + private String fileUrl; + + @Schema(description = "出库项列表", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "出库项列表不能为空") + @Valid + private List items; + + @Data + public static class Item { + + @Schema(description = "出库项编号", example = "11756") + private Long id; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "仓库编号不能为空") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品编号不能为空") + private Long productId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "账面数量(当前库存)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "账面数量不能为空") + private BigDecimal stockCount; + + @Schema(description = "实际数量(实际库存)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "实际数量不能为空") + private BigDecimal actualCount; + + @Schema(description = "盈亏数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "盈亏数量不能为空") + private BigDecimal count; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInPageReqVO.java new file mode 100644 index 000000000..02e3db37a --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInPageReqVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +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 = "管理后台 - ERP 其它入库单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpStockInPageReqVO extends PageParam { + + @Schema(description = "入库单号", example = "S123") + private String no; + + @Schema(description = "供应商编号", example = "3113") + private Long supplierId; + + @Schema(description = "入库时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] inTime; + + @Schema(description = "状态", example = "10") + @InEnum(ErpAuditStatus.class) + private Integer status; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "产品编号", example = "1") + private Long productId; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java new file mode 100644 index 000000000..077b9dd1b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java @@ -0,0 +1,110 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.module.erp.enums.DictTypeConstants.AUDIT_STATUS; + +@Schema(description = "管理后台 - ERP 其它入库单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpStockInRespVO { + + @Schema(description = "入库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @ExcelProperty("入库编号") + private Long id; + + @Schema(description = "入库单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "S123") + @ExcelProperty("入库单号") + private String no; + + @Schema(description = "供应商编号", example = "3113") + private Long supplierId; + @Schema(description = "供应商名称", example = "芋道") + @ExcelProperty("供应商名称") + private String supplierName; + + @Schema(description = "入库时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("入库时间") + private LocalDateTime inTime; + + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") + @ExcelProperty("合计数量") + private BigDecimal totalCount; + + @Schema(description = "合计金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @ExcelProperty("合计金额") + private BigDecimal totalPrice; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(AUDIT_STATUS) + private Integer status; + + @Schema(description = "备注", example = "随便") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") + private String fileUrl; + + @Schema(description = "创建人", example = "芋道") + private String creator; + @Schema(description = "创建人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "入库项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("产品信息") + private String productNames; + + @Data + public static class Item { + + @Schema(description = "入库项编号", example = "11756") + private Long id; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productId; + + @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal count; + + @Schema(description = "备注", example = "随便") + private String remark; + + // ========== 关联字段 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") + private String productBarCode; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") + private String productUnitName; + + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal stockCount; // 该字段仅仅在“详情”和“编辑”时使用 + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java new file mode 100644 index 000000000..ef686d82c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 其它入库单新增/修改 Request VO") +@Data +public class ErpStockInSaveReqVO { + + @Schema(description = "入库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private Long id; + + @Schema(description = "供应商编号", example = "3113") + private Long supplierId; + + @Schema(description = "入库时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "入库时间不能为空") + private LocalDateTime inTime; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") + private String fileUrl; + + @Schema(description = "入库项列表", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "入库项列表不能为空") + @Valid + private List items; + + @Data + public static class Item { + + @Schema(description = "入库项编号", example = "11756") + private Long id; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "仓库编号不能为空") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品编号不能为空") + private Long productId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMovePageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMovePageReqVO.java new file mode 100644 index 000000000..98a1fe95e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMovePageReqVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +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 = "管理后台 - ERP 库存调拨单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpStockMovePageReqVO extends PageParam { + + @Schema(description = "调拨单号", example = "S123") + private String no; + + @Schema(description = "调拨时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] moveTime; + + @Schema(description = "状态", example = "10") + @InEnum(ErpAuditStatus.class) + private Integer status; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "产品编号", example = "1") + private Long productId; + + @Schema(description = "调出仓库编号", example = "1") + private Long fromWarehouseId; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java new file mode 100644 index 000000000..799ddc3f1 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java @@ -0,0 +1,107 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.module.erp.enums.DictTypeConstants.AUDIT_STATUS; + +@Schema(description = "管理后台 - ERP 库存调拨单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpStockMoveRespVO { + + @Schema(description = "调拨编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @ExcelProperty("调拨编号") + private Long id; + + @Schema(description = "调拨单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "S123") + @ExcelProperty("调拨单号") + private String no; + + @Schema(description = "调拨时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("调拨时间") + private LocalDateTime moveTime; + + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") + @ExcelProperty("合计数量") + private BigDecimal totalCount; + + @Schema(description = "合计金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @ExcelProperty("合计金额") + private BigDecimal totalPrice; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(AUDIT_STATUS) + private Integer status; + + @Schema(description = "备注", example = "随便") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") + private String fileUrl; + + @Schema(description = "创建人", example = "芋道") + private String creator; + @Schema(description = "创建人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "调拨项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("产品信息") + private String productNames; + + @Data + public static class Item { + + @Schema(description = "调拨项编号", example = "11756") + private Long id; + + @Schema(description = "调出仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long fromWarehouseId; + + @Schema(description = "调入仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "888") + private Long toWarehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productId; + + @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal count; + + @Schema(description = "备注", example = "随便") + private String remark; + + // ========== 关联字段 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") + private String productBarCode; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") + private String productUnitName; + + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal stockCount; // 该字段仅仅在“详情”和“编辑”时使用 + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveSaveReqVO.java new file mode 100644 index 000000000..dc803531b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveSaveReqVO.java @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move; + +import cn.hutool.core.util.ObjectUtil; +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.Valid; +import javax.validation.constraints.AssertTrue; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 库存调拨单新增/修改 Request VO") +@Data +public class ErpStockMoveSaveReqVO { + + @Schema(description = "调拨编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private Long id; + + @Schema(description = "客户编号", example = "3113") + private Long customerId; + + @Schema(description = "调拨时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "调拨时间不能为空") + private LocalDateTime moveTime; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") + private String fileUrl; + + @Schema(description = "调拨项列表", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "调拨项列表不能为空") + @Valid + private List items; + + @Data + public static class Item { + + @Schema(description = "调拨项编号", example = "11756") + private Long id; + + @Schema(description = "调出仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "调出仓库编号不能为空") + private Long fromWarehouseId; + + @Schema(description = "调入仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "888") + @NotNull(message = "调入仓库编号不能为空") + private Long toWarehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品编号不能为空") + private Long productId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "备注", example = "随便") + private String remark; + + @AssertTrue(message = "调出、调仓仓库不能相同") + @JsonIgnore + public boolean isWarehouseValid() { + return ObjectUtil.notEqual(fromWarehouseId, toWarehouseId); + } + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutPageReqVO.java new file mode 100644 index 000000000..5f6558b19 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutPageReqVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +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 = "管理后台 - ERP 其它出库单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpStockOutPageReqVO extends PageParam { + + @Schema(description = "出库单号", example = "S123") + private String no; + + @Schema(description = "客户编号", example = "3113") + private Long customerId; + + @Schema(description = "出库时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] outTime; + + @Schema(description = "状态", example = "10") + @InEnum(ErpAuditStatus.class) + private Integer status; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "产品编号", example = "1") + private Long productId; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java new file mode 100644 index 000000000..22a88e7c9 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java @@ -0,0 +1,110 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.module.erp.enums.DictTypeConstants.AUDIT_STATUS; + +@Schema(description = "管理后台 - ERP 其它出库单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpStockOutRespVO { + + @Schema(description = "出库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @ExcelProperty("出库编号") + private Long id; + + @Schema(description = "出库单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "S123") + @ExcelProperty("出库单号") + private String no; + + @Schema(description = "客户编号", example = "3113") + private Long customerId; + @Schema(description = "客户名称", example = "芋道") + @ExcelProperty("客户名称") + private String customerName; + + @Schema(description = "出库时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("出库时间") + private LocalDateTime outTime; + + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") + @ExcelProperty("合计数量") + private BigDecimal totalCount; + + @Schema(description = "合计金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @ExcelProperty("合计金额") + private BigDecimal totalPrice; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(AUDIT_STATUS) + private Integer status; + + @Schema(description = "备注", example = "随便") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") + private String fileUrl; + + @Schema(description = "创建人", example = "芋道") + private String creator; + @Schema(description = "创建人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "出库项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("产品信息") + private String productNames; + + @Data + public static class Item { + + @Schema(description = "出库项编号", example = "11756") + private Long id; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productId; + + @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal count; + + @Schema(description = "备注", example = "随便") + private String remark; + + // ========== 关联字段 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") + private String productBarCode; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") + private String productUnitName; + + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal stockCount; // 该字段仅仅在“详情”和“编辑”时使用 + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java new file mode 100644 index 000000000..263058709 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 其它出库单新增/修改 Request VO") +@Data +public class ErpStockOutSaveReqVO { + + @Schema(description = "出库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private Long id; + + @Schema(description = "客户编号", example = "3113") + private Long customerId; + + @Schema(description = "出库时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出库时间不能为空") + private LocalDateTime outTime; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") + private String fileUrl; + + @Schema(description = "出库项列表", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "出库项列表不能为空") + @Valid + private List items; + + @Data + public static class Item { + + @Schema(description = "出库项编号", example = "11756") + private Long id; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "仓库编号不能为空") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品编号不能为空") + private Long productId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordPageReqVO.java new file mode 100644 index 000000000..c478e4fef --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordPageReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - ERP 产品库存明细分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpStockRecordPageReqVO extends PageParam { + + @Schema(description = "产品编号", example = "10625") + private Long productId; + + @Schema(description = "仓库编号", example = "32407") + private Long warehouseId; + + @Schema(description = "业务类型", example = "10") + private Integer bizType; + + @Schema(description = "业务单号", example = "Z110") + private String bizNo; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordRespVO.java new file mode 100644 index 000000000..ff4b3e12a --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordRespVO.java @@ -0,0 +1,87 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.erp.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - ERP 产品库存明细 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpStockRecordRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18909") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10625") + private Long productId; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32407") + private Long warehouseId; + + @Schema(description = "出入库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "11084") + @ExcelProperty("出入库数量") + private BigDecimal count; + + @Schema(description = "总库存量", requiredMode = Schema.RequiredMode.REQUIRED, example = "4307") + @ExcelProperty("总库存量") + private BigDecimal totalCount; + + @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty(value = "业务类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.STOCK_RECORD_BIZ_TYPE) + private Integer bizType; + + @Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "27093") + @ExcelProperty("业务编号") + private Long bizId; + + @Schema(description = "业务项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23516") + @ExcelProperty("业务项编号") + private Long bizItemId; + + @Schema(description = "业务单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "Z110") + @ExcelProperty("业务单号") + private String bizNo; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "创建人", requiredMode = Schema.RequiredMode.REQUIRED, example = "25682") + private String creator; + + // ========== 产品信息 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "苹果") + @ExcelProperty("产品名称") + private String productName; + + @Schema(description = "产品分类", requiredMode = Schema.RequiredMode.REQUIRED, example = "水果") + @ExcelProperty("产品分类") + private String categoryName; + + @Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "个") + @ExcelProperty("单位") + private String unitName; + + // ========== 仓库信息 ========== + + @Schema(description = "仓库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @ExcelProperty("仓库名称") + private String warehouseName; + + // ========== 用户信息 ========== + + @Schema(description = "创建人", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + @ExcelProperty("创建人") + private String creatorName; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockPageReqVO.java new file mode 100644 index 000000000..f7f3fa343 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockPageReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock; + +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 = "管理后台 - ERP 库存分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpStockPageReqVO extends PageParam { + + @Schema(description = "产品编号", example = "19614") + private Long productId; + + @Schema(description = "仓库编号", example = "2802") + private Long warehouseId; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java new file mode 100644 index 000000000..06366a0dd --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - ERP 库存 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpStockRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17086") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "19614") + private Long productId; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2802") + private Long warehouseId; + + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "21935") + @ExcelProperty("库存数量") + private BigDecimal count; + + // ========== 产品信息 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "苹果") + @ExcelProperty("产品名称") + private String productName; + + @Schema(description = "产品分类", requiredMode = Schema.RequiredMode.REQUIRED, example = "水果") + @ExcelProperty("产品分类") + private String categoryName; + + @Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "个") + @ExcelProperty("单位") + private String unitName; + + // ========== 仓库信息 ========== + + @Schema(description = "仓库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @ExcelProperty("仓库名称") + private String warehouseName; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehousePageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehousePageReqVO.java new file mode 100644 index 000000000..2accf9a0f --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehousePageReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - ERP 仓库分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpWarehousePageReqVO extends PageParam { + + @Schema(description = "仓库名称", example = "李四") + private String name; + + @Schema(description = "开启状态", example = "1") + @InEnum(CommonStatusEnum.class) + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java new file mode 100644 index 000000000..188d42699 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - ERP 仓库 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpWarehouseRespVO { + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11614") + @ExcelProperty("仓库编号") + private Long id; + + @Schema(description = "仓库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @ExcelProperty("仓库名称") + private String name; + + @Schema(description = "仓库地址", example = "上海陆家嘴") + @ExcelProperty("仓库地址") + private String address; + + @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty("排序") + private Long sort; + + @Schema(description = "备注", example = "随便") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "负责人", example = "芋头") + @ExcelProperty("负责人") + private String principal; + + @Schema(description = "仓储费,单位:元", example = "13973") + @ExcelProperty("仓储费,单位:元") + private BigDecimal warehousePrice; + + @Schema(description = "搬运费,单位:元", example = "9903") + @ExcelProperty("搬运费,单位:元") + private BigDecimal truckagePrice; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "开启状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "是否默认", example = "1") + @ExcelProperty("是否默认") + private Boolean defaultStatus; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSaveReqVO.java new file mode 100644 index 000000000..5105360fe --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSaveReqVO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - ERP 仓库新增/修改 Request VO") +@Data +public class ErpWarehouseSaveReqVO { + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11614") + private Long id; + + @Schema(description = "仓库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @NotEmpty(message = "仓库名称不能为空") + private String name; + + @Schema(description = "仓库地址", example = "上海陆家嘴") + private String address; + + @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @NotNull(message = "排序不能为空") + private Long sort; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "负责人", example = "芋头") + private String principal; + + @Schema(description = "仓储费,单位:元", example = "13973") + private BigDecimal warehousePrice; + + @Schema(description = "搬运费,单位:元", example = "9903") + private BigDecimal truckagePrice; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "开启状态不能为空") + @InEnum(CommonStatusEnum.class) + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/package-info.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/package-info.java new file mode 100644 index 000000000..ef0e5accf --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/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.erp.controller; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpAccountDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpAccountDO.java new file mode 100644 index 000000000..fe01cc228 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpAccountDO.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.finance; + +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.*; + +/** + * ERP 结算账户 DO + * + * @author 芋道源码 + */ +@TableName("erp_account") +@KeySequence("erp_account_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpAccountDO extends BaseDO { + + /** + * 结算账户编号 + */ + @TableId + private Long id; + /** + * 账户名称 + */ + private String name; + /** + * 账户编码 + */ + private String no; + /** + * 备注 + */ + private String remark; + /** + * 开启状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 排序 + */ + private Integer sort; + /** + * 是否默认 + */ + private Boolean defaultStatus; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentDO.java new file mode 100644 index 000000000..edb55edbf --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentDO.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.finance; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; +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; + +/** + * ERP 付款单 DO + * + * @author 芋道源码 + */ +@TableName("erp_finance_payment") +@KeySequence("erp_finance_payment_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpFinancePaymentDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 付款单号 + */ + private String no; + /** + * 付款状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 付款时间 + */ + private LocalDateTime paymentTime; + /** + * 财务人员编号 + * + * 关联 AdminUserDO 的 id 字段 + */ + private Long financeUserId; + /** + * 供应商编号 + * + * 关联 {@link ErpSupplierDO#getId()} + */ + private Long supplierId; + /** + * 付款账户编号 + * + * 关联 {@link ErpAccountDO#getId()} + */ + private Long accountId; + + /** + * 合计价格,单位:元 + */ + private BigDecimal totalPrice; + /** + * 优惠金额,单位:元 + */ + private BigDecimal discountPrice; + /** + * 实付金额,单位:分 + * + * paymentPrice = totalPrice - discountPrice + */ + private BigDecimal paymentPrice; + + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentItemDO.java new file mode 100644 index 000000000..dd5bc5f69 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentItemDO.java @@ -0,0 +1,75 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.finance; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 付款项 DO + * + * @author 芋道源码 + */ +@TableName("erp_finance_payment_item") +@KeySequence("erp_finance_payment_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpFinancePaymentItemDO extends BaseDO { + + /** + * 入库项编号 + */ + @TableId + private Long id; + /** + * 付款单编号 + * + * 关联 {@link ErpFinancePaymentDO#getId()} + */ + private Long paymentId; + + /** + * 业务类型 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.common.ErpBizTypeEnum} 的采购入库、退货 + */ + private Integer bizType; + /** + * 业务编号 + * + * 例如说:{@link ErpPurchaseInDO#getId()} + */ + private Long bizId; + /** + * 业务单号 + * + * 例如说:{@link ErpPurchaseInDO#getNo()} + */ + private String bizNo; + + /** + * 应付金额,单位:分 + */ + private BigDecimal totalPrice; + /** + * 已付金额,单位:分 + */ + private BigDecimal paidPrice; + /** + * 本次付款,单位:分 + */ + private BigDecimal paymentPrice; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptDO.java new file mode 100644 index 000000000..46a559505 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptDO.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.finance; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; +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; + +/** + * ERP 收款单 DO + * + * @author 芋道源码 + */ +@TableName("erp_finance_receipt") +@KeySequence("erp_finance_receipt_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpFinanceReceiptDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 收款单号 + */ + private String no; + /** + * 收款状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 收款时间 + */ + private LocalDateTime receiptTime; + /** + * 财务人员编号 + * + * 关联 AdminUserDO 的 id 字段 + */ + private Long financeUserId; + /** + * 客户编号 + * + * 关联 {@link ErpCustomerDO#getId()} + */ + private Long customerId; + /** + * 收款账户编号 + * + * 关联 {@link ErpAccountDO#getId()} + */ + private Long accountId; + + /** + * 合计价格,单位:元 + */ + private BigDecimal totalPrice; + /** + * 优惠金额,单位:元 + */ + private BigDecimal discountPrice; + /** + * 实付金额,单位:分 + * + * receiptPrice = totalPrice - discountPrice + */ + private BigDecimal receiptPrice; + + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptItemDO.java new file mode 100644 index 000000000..87f051d5c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptItemDO.java @@ -0,0 +1,75 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.finance; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 收款项 DO + * + * @author 芋道源码 + */ +@TableName("erp_finance_receipt_item") +@KeySequence("erp_finance_receipt_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpFinanceReceiptItemDO extends BaseDO { + + /** + * 入库项编号 + */ + @TableId + private Long id; + /** + * 收款单编号 + * + * 关联 {@link ErpFinanceReceiptDO#getId()} + */ + private Long receiptId; + + /** + * 业务类型 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.common.ErpBizTypeEnum} 的销售出库、退货 + */ + private Integer bizType; + /** + * 业务编号 + * + * 例如说:{@link ErpSaleOutDO#getId()} + */ + private Long bizId; + /** + * 业务单号 + * + * 例如说:{@link ErpSaleOutDO#getNo()} + */ + private String bizNo; + + /** + * 应收金额,单位:分 + */ + private BigDecimal totalPrice; + /** + * 已收金额,单位:分 + */ + private BigDecimal receiptedPrice; + /** + * 本次收款,单位:分 + */ + private BigDecimal receiptPrice; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductCategoryDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductCategoryDO.java new file mode 100644 index 000000000..4c6225158 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductCategoryDO.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.product; + +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.*; + +/** + * ERP 产品分类 DO + * + * @author 芋道源码 + */ +@TableName("erp_product_category") +@KeySequence("erp_product_category_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpProductCategoryDO extends BaseDO { + + public static final Long PARENT_ID_ROOT = 0L; + + /** + * 分类编号 + */ + @TableId + private Long id; + /** + * 父分类编号 + */ + private Long parentId; + /** + * 分类名称 + */ + private String name; + /** + * 分类编码 + */ + private String code; + /** + * 分类排序 + */ + private Integer sort; + /** + * 开启状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductDO.java new file mode 100644 index 000000000..31e4aa2d9 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductDO.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.product; + +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; + +/** + * ERP 产品 DO + * + * @author 芋道源码 + */ +@TableName("erp_product") +@KeySequence("erp_product_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpProductDO extends BaseDO { + + /** + * 产品编号 + */ + @TableId + private Long id; + /** + * 产品名称 + */ + private String name; + /** + * 产品条码 + */ + private String barCode; + /** + * 产品分类编号 + * + * 关联 {@link ErpProductCategoryDO#getId()} + */ + private Long categoryId; + /** + * 单位编号 + * + * 关联 {@link ErpProductUnitDO#getId()} + */ + private Long unitId; + /** + * 产品状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 产品规格 + */ + private String standard; + /** + * 产品备注 + */ + private String remark; + /** + * 保质期天数 + */ + private Integer expiryDay; + /** + * 基础重量(kg) + */ + private BigDecimal weight; + /** + * 采购价格,单位:元 + */ + private BigDecimal purchasePrice; + /** + * 销售价格,单位:元 + */ + private BigDecimal salePrice; + /** + * 最低价格,单位:元 + */ + private BigDecimal minPrice; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductUnitDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductUnitDO.java new file mode 100644 index 000000000..73c96c290 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductUnitDO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.product; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * ERP 产品单位 DO + * + * @author 芋道源码 + */ +@TableName("erp_product_unit") +@KeySequence("erp_product_unit_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpProductUnitDO extends BaseDO { + + /** + * 单位编号 + */ + @TableId + private Long id; + /** + * 单位名字 + */ + private String name; + /** + * 单位状态 + */ + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java new file mode 100644 index 000000000..b8186f509 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java @@ -0,0 +1,122 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.purchase; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +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; + +/** + * ERP 采购入库 DO + * + * @author 芋道源码 + */ +@TableName(value = "erp_purchase_in") +@KeySequence("erp_purchase_in_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpPurchaseInDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 采购入库单号 + */ + private String no; + /** + * 入库状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 供应商编号 + * + * 关联 {@link ErpSupplierDO#getId()} + */ + private Long supplierId; + /** + * 结算账户编号 + * + * 关联 {@link ErpAccountDO#getId()} + */ + private Long accountId; + /** + * 入库时间 + */ + private LocalDateTime inTime; + + /** + * 采购订单编号 + * + * 关联 {@link ErpPurchaseOrderDO#getId()} + */ + private Long orderId; + /** + * 采购订单号 + * + * 冗余 {@link ErpPurchaseOrderDO#getNo()} + */ + private String orderNo; + + /** + * 合计数量 + */ + private BigDecimal totalCount; + /** + * 最终合计价格,单位:元 + * + * totalPrice = totalProductPrice + totalTaxPrice - discountPrice + otherPrice + */ + private BigDecimal totalPrice; + /** + * 已支付金额,单位:元 + * + * 目的:和 {@link cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO} 结合,记录已支付金额 + */ + private BigDecimal paymentPrice; + + /** + * 合计产品价格,单位:元 + */ + private BigDecimal totalProductPrice; + /** + * 合计税额,单位:元 + */ + private BigDecimal totalTaxPrice; + /** + * 优惠率,百分比 + */ + private BigDecimal discountPercent; + /** + * 优惠金额,单位:元 + * + * discountPrice = (totalProductPrice + totalTaxPrice) * discountPercent + */ + private BigDecimal discountPrice; + /** + * 其它金额,单位:元 + */ + private BigDecimal otherPrice; + + /** + * 附件地址 + */ + private String fileUrl; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInItemDO.java new file mode 100644 index 000000000..1597bc10b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInItemDO.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.purchase; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 采购入库项 DO + * + * @author 芋道源码 + */ +@TableName("erp_purchase_in_items") +@KeySequence("erp_purchase_in_items_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpPurchaseInItemDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 采购入库编号 + * + * 关联 {@link ErpPurchaseInDO##getId()} + */ + private Long inId; + /** + * 采购订单项编号 + * + * 关联 {@link ErpPurchaseOrderItemDO#getId()} + * 目的:方便更新关联的采购订单项的入库数量 + */ + private Long orderItemId; + /** + * 仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 产品单位单位 + * + * 冗余 {@link ErpProductDO#getUnitId()} + */ + private Long productUnitId; + + /** + * 产品单位单价,单位:元 + */ + private BigDecimal productPrice; + /** + * 数量 + */ + private BigDecimal count; + /** + * 总价,单位:元 + * + * totalPrice = productPrice * count + */ + private BigDecimal totalPrice; + /** + * 税率,百分比 + */ + private BigDecimal taxPercent; + /** + * 税额,单位:元 + * + * taxPrice = totalPrice * taxPercent + */ + private BigDecimal taxPrice; + + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderDO.java new file mode 100644 index 000000000..bba1542e3 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderDO.java @@ -0,0 +1,115 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.purchase; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +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; + +/** + * ERP 采购订单 DO + * + * @author 芋道源码 + */ +@TableName(value = "erp_purchase_order") +@KeySequence("erp_purchase_order_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpPurchaseOrderDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 采购订单号 + */ + private String no; + /** + * 采购状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 供应商编号 + * + * 关联 {@link ErpSupplierDO#getId()} + */ + private Long supplierId; + /** + * 结算账户编号 + * + * 关联 {@link ErpAccountDO#getId()} + */ + private Long accountId; + /** + * 下单时间 + */ + private LocalDateTime orderTime; + + /** + * 合计数量 + */ + private BigDecimal totalCount; + /** + * 最终合计价格,单位:元 + * + * totalPrice = totalProductPrice + totalTaxPrice - discountPrice + */ + private BigDecimal totalPrice; + + /** + * 合计产品价格,单位:元 + */ + private BigDecimal totalProductPrice; + /** + * 合计税额,单位:元 + */ + private BigDecimal totalTaxPrice; + /** + * 优惠率,百分比 + */ + private BigDecimal discountPercent; + /** + * 优惠金额,单位:元 + * + * discountPrice = (totalProductPrice + totalTaxPrice) * discountPercent + */ + private BigDecimal discountPrice; + /** + * 定金金额,单位:元 + */ + private BigDecimal depositPrice; + + /** + * 附件地址 + */ + private String fileUrl; + /** + * 备注 + */ + private String remark; + + // ========== 采购入库 ========== + /** + * 采购入库数量 + */ + private BigDecimal inCount; + + // ========== 采购退货(出库)) ========== + /** + * 采购退货数量 + */ + private BigDecimal returnCount; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderItemDO.java new file mode 100644 index 000000000..aa54d336b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderItemDO.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.purchase; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 采购订单项 DO + * + * @author 芋道源码 + */ +@TableName("erp_purchase_order_items") +@KeySequence("erp_purchase_order_items_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpPurchaseOrderItemDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 采购订单编号 + * + * 关联 {@link ErpPurchaseOrderDO#getId()} + */ + private Long orderId; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 产品单位单位 + * + * 冗余 {@link ErpProductDO#getUnitId()} + */ + private Long productUnitId; + + /** + * 产品单位单价,单位:元 + */ + private BigDecimal productPrice; + /** + * 数量 + */ + private BigDecimal count; + /** + * 总价,单位:元 + * + * totalPrice = productPrice * count + */ + private BigDecimal totalPrice; + /** + * 税率,百分比 + */ + private BigDecimal taxPercent; + /** + * 税额,单位:元 + * + * taxPrice = totalPrice * taxPercent + */ + private BigDecimal taxPrice; + + /** + * 备注 + */ + private String remark; + + // ========== 采购入库 ========== + /** + * 采购入库数量 + */ + private BigDecimal inCount; + + // ========== 采购退货(出库)) ========== + /** + * 采购退货数量 + */ + private BigDecimal returnCount; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnDO.java new file mode 100644 index 000000000..4189e0adc --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnDO.java @@ -0,0 +1,122 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.purchase; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +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; + +/** + * ERP 采购退货 DO + * + * @author 芋道源码 + */ +@TableName(value = "erp_purchase_return") +@KeySequence("erp_purchase_return_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpPurchaseReturnDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 采购退货单号 + */ + private String no; + /** + * 退货状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 供应商编号 + * + * 关联 {@link ErpSupplierDO#getId()} + */ + private Long supplierId; + /** + * 结算账户编号 + * + * 关联 {@link ErpAccountDO#getId()} + */ + private Long accountId; + /** + * 退货时间 + */ + private LocalDateTime returnTime; + + /** + * 采购订单编号 + * + * 关联 {@link ErpPurchaseOrderDO#getId()} + */ + private Long orderId; + /** + * 采购订单号 + * + * 冗余 {@link ErpPurchaseOrderDO#getNo()} + */ + private String orderNo; + + /** + * 合计数量 + */ + private BigDecimal totalCount; + /** + * 最终合计价格,单位:元 + * + * totalPrice = totalProductPrice + totalTaxPrice - discountPrice + otherPrice + */ + private BigDecimal totalPrice; + /** + * 已退款金额,单位:元 + * + * 目的:和 {@link cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO} 结合,记录已支付金额 + */ + private BigDecimal refundPrice; + + /** + * 合计产品价格,单位:元 + */ + private BigDecimal totalProductPrice; + /** + * 合计税额,单位:元 + */ + private BigDecimal totalTaxPrice; + /** + * 优惠率,百分比 + */ + private BigDecimal discountPercent; + /** + * 优惠金额,单位:元 + * + * discountPrice = (totalProductPrice + totalTaxPrice) * discountPercent + */ + private BigDecimal discountPrice; + /** + * 其它金额,单位:元 + */ + private BigDecimal otherPrice; + + /** + * 附件地址 + */ + private String fileUrl; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnItemDO.java new file mode 100644 index 000000000..1e1713277 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnItemDO.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.purchase; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 采购退货项 DO + * + * @author 芋道源码 + */ +@TableName("erp_purchase_return_items") +@KeySequence("erp_purchase_return_items_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpPurchaseReturnItemDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 采购退货编号 + * + * 关联 {@link ErpPurchaseReturnDO##getId()} + */ + private Long returnId; + /** + * 采购订单项编号 + * + * 关联 {@link ErpPurchaseOrderItemDO#getId()} + * 目的:方便更新关联的采购订单项的退货数量 + */ + private Long orderItemId; + /** + * 仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 产品单位单位 + * + * 冗余 {@link ErpProductDO#getUnitId()} + */ + private Long productUnitId; + + /** + * 产品单位单价,单位:元 + */ + private BigDecimal productPrice; + /** + * 数量 + */ + private BigDecimal count; + /** + * 总价,单位:元 + * + * totalPrice = productPrice * count + */ + private BigDecimal totalPrice; + /** + * 税率,百分比 + */ + private BigDecimal taxPercent; + /** + * 税额,单位:元 + * + * taxPrice = totalPrice * taxPercent + */ + private BigDecimal taxPrice; + + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpSupplierDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpSupplierDO.java new file mode 100644 index 000000000..6e94c6669 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpSupplierDO.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.purchase; + +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; + +/** + * ERP 供应商 DO + * + * @author 芋道源码 + */ +@TableName("erp_supplier") +@KeySequence("erp_supplier_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpSupplierDO extends BaseDO { + + /** + * 供应商编号 + */ + @TableId + private Long id; + /** + * 供应商名称 + */ + private String name; + /** + * 联系人 + */ + private String contact; + /** + * 手机号码 + */ + private String mobile; + /** + * 联系电话 + */ + private String telephone; + /** + * 电子邮箱 + */ + private String email; + /** + * 传真 + */ + private String fax; + /** + * 备注 + */ + private String remark; + /** + * 开启状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 排序 + */ + private Integer sort; + /** + * 纳税人识别号 + */ + private String taxNo; + /** + * 税率 + */ + private BigDecimal taxPercent; + /** + * 开户行 + */ + private String bankName; + /** + * 开户账号 + */ + private String bankAccount; + /** + * 开户地址 + */ + private String bankAddress; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpCustomerDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpCustomerDO.java new file mode 100644 index 000000000..7bffcc17c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpCustomerDO.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.sale; + +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; + +/** + * ERP 客户 DO + * + * @author 芋道源码 + */ +@TableName("erp_customer") +@KeySequence("erp_customer_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpCustomerDO extends BaseDO { + + /** + * 客户编号 + */ + @TableId + private Long id; + /** + * 客户名称 + */ + private String name; + /** + * 联系人 + */ + private String contact; + /** + * 手机号码 + */ + private String mobile; + /** + * 联系电话 + */ + private String telephone; + /** + * 电子邮箱 + */ + private String email; + /** + * 传真 + */ + private String fax; + /** + * 备注 + */ + private String remark; + /** + * 开启状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 排序 + */ + private Integer sort; + /** + * 纳税人识别号 + */ + private String taxNo; + /** + * 税率 + */ + private BigDecimal taxPercent; + /** + * 开户行 + */ + private String bankName; + /** + * 开户账号 + */ + private String bankAccount; + /** + * 开户地址 + */ + private String bankAddress; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java new file mode 100644 index 000000000..5cdd4344e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java @@ -0,0 +1,121 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.sale; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +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; + +/** + * ERP 销售订单 DO + * + * @author 芋道源码 + */ +@TableName(value = "erp_sale_order") +@KeySequence("erp_sale_order_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpSaleOrderDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 销售订单号 + */ + private String no; + /** + * 销售状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 客户编号 + * + * 关联 {@link ErpCustomerDO#getId()} + */ + private Long customerId; + /** + * 结算账户编号 + * + * 关联 {@link ErpAccountDO#getId()} + */ + private Long accountId; + /** + * 销售员编号 + * + * 关联 AdminUserDO 的 id 字段 + */ + private Long saleUserId; + /** + * 下单时间 + */ + private LocalDateTime orderTime; + + /** + * 合计数量 + */ + private BigDecimal totalCount; + /** + * 最终合计价格,单位:元 + * + * totalPrice = totalProductPrice + totalTaxPrice - discountPrice + */ + private BigDecimal totalPrice; + + /** + * 合计产品价格,单位:元 + */ + private BigDecimal totalProductPrice; + /** + * 合计税额,单位:元 + */ + private BigDecimal totalTaxPrice; + /** + * 优惠率,百分比 + */ + private BigDecimal discountPercent; + /** + * 优惠金额,单位:元 + * + * discountPrice = (totalProductPrice + totalTaxPrice) * discountPercent + */ + private BigDecimal discountPrice; + /** + * 定金金额,单位:元 + */ + private BigDecimal depositPrice; + + /** + * 附件地址 + */ + private String fileUrl; + /** + * 备注 + */ + private String remark; + + // ========== 销售出库 ========== + /** + * 销售出库数量 + */ + private BigDecimal outCount; + + // ========== 销售退货(入库)) ========== + /** + * 销售退货数量 + */ + private BigDecimal returnCount; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java new file mode 100644 index 000000000..4c829765b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.sale; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 销售订单项 DO + * + * @author 芋道源码 + */ +@TableName("erp_sale_order_items") +@KeySequence("erp_sale_order_items_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpSaleOrderItemDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 销售订单编号 + * + * 关联 {@link ErpSaleOrderDO#getId()} + */ + private Long orderId; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 产品单位单位 + * + * 冗余 {@link ErpProductDO#getUnitId()} + */ + private Long productUnitId; + + /** + * 产品单位单价,单位:元 + */ + private BigDecimal productPrice; + /** + * 数量 + */ + private BigDecimal count; + /** + * 总价,单位:元 + * + * totalPrice = productPrice * count + */ + private BigDecimal totalPrice; + /** + * 税率,百分比 + */ + private BigDecimal taxPercent; + /** + * 税额,单位:元 + * + * taxPrice = totalPrice * taxPercent + */ + private BigDecimal taxPrice; + + /** + * 备注 + */ + private String remark; + + // ========== 销售出库 ========== + /** + * 销售出库数量 + */ + private BigDecimal outCount; + + // ========== 销售退货(入库)) ========== + /** + * 销售退货数量 + */ + private BigDecimal returnCount; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java new file mode 100644 index 000000000..65b9d941f --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java @@ -0,0 +1,128 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.sale; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +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; + +/** + * ERP 销售出库 DO + * + * @author 芋道源码 + */ +@TableName(value = "erp_sale_out") +@KeySequence("erp_sale_out_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpSaleOutDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 销售出库单号 + */ + private String no; + /** + * 出库状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 客户编号 + * + * 关联 {@link ErpCustomerDO#getId()} + */ + private Long customerId; + /** + * 结算账户编号 + * + * 关联 {@link ErpAccountDO#getId()} + */ + private Long accountId; + /** + * 销售员编号 + * + * 关联 AdminUserDO 的 id 字段 + */ + private Long saleUserId; + /** + * 出库时间 + */ + private LocalDateTime outTime; + + /** + * 销售订单编号 + * + * 关联 {@link ErpSaleOrderDO#getId()} + */ + private Long orderId; + /** + * 销售订单号 + * + * 冗余 {@link ErpSaleOrderDO#getNo()} + */ + private String orderNo; + + /** + * 合计数量 + */ + private BigDecimal totalCount; + /** + * 最终合计价格,单位:元 + * + * totalPrice = totalProductPrice + totalTaxPrice - discountPrice + otherPrice + */ + private BigDecimal totalPrice; + /** + * 已收款金额,单位:元 + * + * 目的:和 {@link cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptDO} 结合,记录已收款金额 + */ + private BigDecimal receiptPrice; + + /** + * 合计产品价格,单位:元 + */ + private BigDecimal totalProductPrice; + /** + * 合计税额,单位:元 + */ + private BigDecimal totalTaxPrice; + /** + * 优惠率,百分比 + */ + private BigDecimal discountPercent; + /** + * 优惠金额,单位:元 + * + * discountPrice = (totalProductPrice + totalTaxPrice) * discountPercent + */ + private BigDecimal discountPrice; + /** + * 其它金额,单位:元 + */ + private BigDecimal otherPrice; + + /** + * 附件地址 + */ + private String fileUrl; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutItemDO.java new file mode 100644 index 000000000..b9b406413 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutItemDO.java @@ -0,0 +1,96 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.sale; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 销售出库项 DO + * + * @author 芋道源码 + */ +@TableName("erp_sale_out_items") +@KeySequence("erp_sale_out_items_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpSaleOutItemDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 销售出库编号 + * + * 关联 {@link ErpStockOutDO##getId()} + */ + private Long outId; + /** + * 销售订单项编号 + * + * 关联 {@link ErpSaleOrderItemDO#getId()} + * 目的:方便更新关联的销售订单项的出库数量 + */ + private Long orderItemId; + /** + * 仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 产品单位单位 + * + * 冗余 {@link ErpProductDO#getUnitId()} + */ + private Long productUnitId; + + /** + * 产品单位单价,单位:元 + */ + private BigDecimal productPrice; + /** + * 数量 + */ + private BigDecimal count; + /** + * 总价,单位:元 + * + * totalPrice = productPrice * count + */ + private BigDecimal totalPrice; + /** + * 税率,百分比 + */ + private BigDecimal taxPercent; + /** + * 税额,单位:元 + * + * taxPrice = totalPrice * taxPercent + */ + private BigDecimal taxPrice; + + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleReturnDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleReturnDO.java new file mode 100644 index 000000000..ba41ac91b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleReturnDO.java @@ -0,0 +1,128 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.sale; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +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; + +/** + * ERP 销售退货 DO + * + * @author 芋道源码 + */ +@TableName(value = "erp_sale_return") +@KeySequence("erp_sale_return_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpSaleReturnDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 销售退货单号 + */ + private String no; + /** + * 退货状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 客户编号 + * + * 关联 {@link ErpCustomerDO#getId()} + */ + private Long customerId; + /** + * 结算账户编号 + * + * 关联 {@link ErpAccountDO#getId()} + */ + private Long accountId; + /** + * 销售员编号 + * + * 关联 AdminUserDO 的 id 字段 + */ + private Long saleUserId; + /** + * 退货时间 + */ + private LocalDateTime returnTime; + + /** + * 销售订单编号 + * + * 关联 {@link ErpSaleOrderDO#getId()} + */ + private Long orderId; + /** + * 销售订单号 + * + * 冗余 {@link ErpSaleOrderDO#getNo()} + */ + private String orderNo; + + /** + * 合计数量 + */ + private BigDecimal totalCount; + /** + * 最终合计价格,单位:元 + * + * totalPrice = totalProductPrice + totalTaxPrice - discountPrice + otherPrice + */ + private BigDecimal totalPrice; + /** + * 已退款金额,单位:元 + * + * 目的:和 {@link cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptDO} 结合,记录已退款金额 + */ + private BigDecimal refundPrice; + + /** + * 合计产品价格,单位:元 + */ + private BigDecimal totalProductPrice; + /** + * 合计税额,单位:元 + */ + private BigDecimal totalTaxPrice; + /** + * 优惠率,百分比 + */ + private BigDecimal discountPercent; + /** + * 优惠金额,单位:元 + * + * discountPrice = (totalProductPrice + totalTaxPrice) * discountPercent + */ + private BigDecimal discountPrice; + /** + * 其它金额,单位:元 + */ + private BigDecimal otherPrice; + + /** + * 附件地址 + */ + private String fileUrl; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleReturnItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleReturnItemDO.java new file mode 100644 index 000000000..8851d157c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleReturnItemDO.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.sale; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 销售退货项 DO + * + * @author 芋道源码 + */ +@TableName("erp_sale_return_items") +@KeySequence("erp_sale_return_items_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpSaleReturnItemDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 销售退货编号 + * + * 关联 {@link ErpSaleReturnDO##getId()} + */ + private Long returnId; + /** + * 销售订单项编号 + * + * 关联 {@link ErpSaleOrderItemDO#getId()} + * 目的:方便更新关联的销售订单项的退货数量 + */ + private Long orderItemId; + /** + * 仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 产品单位单位 + * + * 冗余 {@link ErpProductDO#getUnitId()} + */ + private Long productUnitId; + + /** + * 产品单位单价,单位:元 + */ + private BigDecimal productPrice; + /** + * 数量 + */ + private BigDecimal count; + /** + * 总价,单位:元 + * + * totalPrice = productPrice * count + */ + private BigDecimal totalPrice; + /** + * 税率,百分比 + */ + private BigDecimal taxPercent; + /** + * 税额,单位:元 + * + * taxPrice = totalPrice * taxPercent + */ + private BigDecimal taxPrice; + + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockCheckDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockCheckDO.java new file mode 100644 index 000000000..e9168275f --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockCheckDO.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.stock; + +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; + +/** + * ERP 库存盘点单 DO + * + * @author 芋道源码 + */ +@TableName("erp_stock_check") +@KeySequence("erp_stock_check_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockCheckDO extends BaseDO { + + /** + * 盘点编号 + */ + @TableId + private Long id; + /** + * 盘点单号 + */ + private String no; + /** + * 盘点时间 + */ + private LocalDateTime checkTime; + /** + * 合计数量 + */ + private BigDecimal totalCount; + /** + * 合计金额,单位:元 + */ + private BigDecimal totalPrice; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + /** + * 附件 URL + */ + private String fileUrl; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockCheckItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockCheckItemDO.java new file mode 100644 index 000000000..c3c4dbf99 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockCheckItemDO.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.stock; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 库存盘点单项 DO + * + * @author 芋道源码 + */ +@TableName("erp_stock_check_item") +@KeySequence("erp_stock_check_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockCheckItemDO extends BaseDO { + + /** + * 盘点项编号 + */ + @TableId + private Long id; + /** + * 盘点编号 + * + * 关联 {@link ErpStockCheckDO#getId()} + */ + private Long checkId; + /** + * 仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 产品单位编号 + * + * 冗余 {@link ErpProductDO#getUnitId()} + */ + private Long productUnitId; + /** + * 产品单价 + */ + private BigDecimal productPrice; + /** + * 账面数量(当前库存) + */ + private BigDecimal stockCount; + /** + * 实际数量(实际库存) + */ + private BigDecimal actualCount; + /** + * 盈亏数量 + * + * count = stockCount - actualCount + */ + private BigDecimal count; + /** + * 合计金额,单位:元 + */ + private BigDecimal totalPrice; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockDO.java new file mode 100644 index 000000000..558c6c6e5 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockDO.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.stock; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 产品库存 DO + * + * @author 芋道源码 + */ +@TableName("erp_stock") +@KeySequence("erp_stock_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库存数量 + */ + private BigDecimal count; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInDO.java new file mode 100644 index 000000000..ee2512ab6 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInDO.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.stock; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; +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; + +/** + * ERP 其它入库单 DO + * + * @author 芋道源码 + */ +@TableName("erp_stock_in") +@KeySequence("erp_stock_in_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockInDO extends BaseDO { + + /** + * 入库编号 + */ + @TableId + private Long id; + /** + * 入库单号 + */ + private String no; + /** + * 供应商编号 + * + * 关联 {@link ErpSupplierDO#getId()} + */ + private Long supplierId; + /** + * 入库时间 + */ + private LocalDateTime inTime; + /** + * 合计数量 + */ + private BigDecimal totalCount; + /** + * 合计金额,单位:元 + */ + private BigDecimal totalPrice; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + /** + * 附件 URL + */ + private String fileUrl; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemDO.java new file mode 100644 index 000000000..3e3ca9c5c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemDO.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.stock; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 其它入库单项 DO + * + * @author 芋道源码 + */ +@TableName("erp_stock_in_item") +@KeySequence("erp_stock_in_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockInItemDO extends BaseDO { + + /** + * 入库项编号 + */ + @TableId + private Long id; + /** + * 入库编号 + * + * 关联 {@link ErpStockInDO#getId()} + */ + private Long inId; + /** + * 仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 产品单位编号 + * + * 冗余 {@link ErpProductDO#getUnitId()} + */ + private Long productUnitId; + /** + * 产品单价 + */ + private BigDecimal productPrice; + /** + * 产品数量 + */ + private BigDecimal count; + /** + * 合计金额,单位:元 + */ + private BigDecimal totalPrice; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveDO.java new file mode 100644 index 000000000..682b33104 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveDO.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.stock; + +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; + +/** + * ERP 库存调拨单 DO + * + * @author 芋道源码 + */ +@TableName("erp_stock_move") +@KeySequence("erp_stock_move_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockMoveDO extends BaseDO { + + /** + * 调拨编号 + */ + @TableId + private Long id; + /** + * 调拨单号 + */ + private String no; + /** + * 调拨时间 + */ + private LocalDateTime moveTime; + /** + * 合计数量 + */ + private BigDecimal totalCount; + /** + * 合计金额,单位:元 + */ + private BigDecimal totalPrice; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + /** + * 附件 URL + */ + private String fileUrl; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveItemDO.java new file mode 100644 index 000000000..aee203670 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveItemDO.java @@ -0,0 +1,79 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.stock; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 库存调拨单项 DO + * + * @author 芋道源码 + */ +@TableName("erp_stock_move_item") +@KeySequence("erp_stock_move_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockMoveItemDO extends BaseDO { + + /** + * 调拨项编号 + */ + @TableId + private Long id; + /** + * 调拨编号 + * + * 关联 {@link ErpStockMoveDO#getId()} + */ + private Long moveId; + /** + * 调出仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long fromWarehouseId; + /** + * 调入仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long toWarehouseId; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 产品单位编号 + * + * 冗余 {@link ErpProductDO#getUnitId()} + */ + private Long productUnitId; + /** + * 产品单价 + */ + private BigDecimal productPrice; + /** + * 产品数量 + */ + private BigDecimal count; + /** + * 合计金额,单位:元 + */ + private BigDecimal totalPrice; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutDO.java new file mode 100644 index 000000000..e0b337adb --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutDO.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.stock; + +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; + +/** + * ERP 其它出库单 DO + * + * @author 芋道源码 + */ +@TableName("erp_stock_out") +@KeySequence("erp_stock_out_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockOutDO extends BaseDO { + + /** + * 出库编号 + */ + @TableId + private Long id; + /** + * 出库单号 + */ + private String no; + /** + * 客户编号 + * + * TODO 芋艿:待关联 + */ + private Long customerId; + /** + * 出库时间 + */ + private LocalDateTime outTime; + /** + * 合计数量 + */ + private BigDecimal totalCount; + /** + * 合计金额,单位:元 + */ + private BigDecimal totalPrice; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + /** + * 附件 URL + */ + private String fileUrl; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemDO.java new file mode 100644 index 000000000..065c5255a --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemDO.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.stock; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 其它出库单项 DO + * + * @author 芋道源码 + */ +@TableName("erp_stock_out_item") +@KeySequence("erp_stock_out_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockOutItemDO extends BaseDO { + + /** + * 出库项编号 + */ + @TableId + private Long id; + /** + * 出库编号 + * + * 关联 {@link ErpStockOutDO#getId()} + */ + private Long outId; + /** + * 仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 产品单位编号 + * + * 冗余 {@link ErpProductDO#getUnitId()} + */ + private Long productUnitId; + /** + * 产品单价 + */ + private BigDecimal productPrice; + /** + * 产品数量 + */ + private BigDecimal count; + /** + * 合计金额,单位:元 + */ + private BigDecimal totalPrice; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockRecordDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockRecordDO.java new file mode 100644 index 000000000..7bc5e5a01 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockRecordDO.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.stock; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 产品库存明细 DO + * + * @author 芋道源码 + */ +@TableName("erp_stock_record") +@KeySequence("erp_stock_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockRecordDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 出入库数量 + * + * 正数,表示入库;负数,表示出库 + */ + private BigDecimal count; + /** + * 总库存量 + * + * 出入库之后,目前的库存量 + */ + private BigDecimal totalCount; + /** + * 业务类型 + * + * 枚举 {@link ErpStockRecordBizTypeEnum} + */ + private Integer bizType; + /** + * 业务编号 + * + * 例如说:{@link ErpStockInDO#getId()} + */ + private Long bizId; + /** + * 业务项编号 + * + * 例如说:{@link ErpStockInItemDO#getId()} + */ + private Long bizItemId; + /** + * 业务单号 + * + * 例如说:{@link ErpStockInDO#getNo()} + */ + private String bizNo; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpWarehouseDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpWarehouseDO.java new file mode 100644 index 000000000..4f206173f --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpWarehouseDO.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.stock; + +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; + +/** + * ERP 仓库 DO + * + * @author 芋道源码 + */ +@TableName("erp_warehouse") +@KeySequence("erp_warehouse_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpWarehouseDO extends BaseDO { + + /** + * 仓库编号 + */ + @TableId + private Long id; + /** + * 仓库名称 + */ + private String name; + /** + * 仓库地址 + */ + private String address; + /** + * 排序 + */ + private Long sort; + /** + * 备注 + */ + private String remark; + /** + * 负责人 + */ + private String principal; + /** + * 仓储费,单位:元 + */ + private BigDecimal warehousePrice; + /** + * 搬运费,单位:元 + */ + private BigDecimal truckagePrice; + /** + * 开启状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 是否默认 + */ + private Boolean defaultStatus; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpAccountMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpAccountMapper.java new file mode 100644 index 000000000..2f98147e2 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpAccountMapper.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.finance; + +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.erp.controller.admin.finance.vo.account.ErpAccountPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * ERP 结算账户 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpAccountMapper extends BaseMapperX { + + default PageResult selectPage(ErpAccountPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ErpAccountDO::getName, reqVO.getName()) + .likeIfPresent(ErpAccountDO::getNo, reqVO.getNo()) + .eqIfPresent(ErpAccountDO::getRemark, reqVO.getRemark()) + .orderByDesc(ErpAccountDO::getId)); + } + + default ErpAccountDO selectByDefaultStatus() { + return selectOne(ErpAccountDO::getDefaultStatus, true); + } + + default List selectListByStatus(Integer status) { + return selectList(ErpAccountDO::getStatus, status); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentItemMapper.java new file mode 100644 index 000000000..7787e8d70 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentItemMapper.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.finance; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentItemDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * ERP 付款单项 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpFinancePaymentItemMapper extends BaseMapperX { + + default List selectListByPaymentId(Long paymentId) { + return selectList(ErpFinancePaymentItemDO::getPaymentId, paymentId); + } + + default List selectListByPaymentIds(Collection paymentIds) { + return selectList(ErpFinancePaymentItemDO::getPaymentId, paymentIds); + } + + default BigDecimal selectPaymentPriceSumByBizIdAndBizType(Long bizId, Integer bizType) { + // SQL sum 查询 + List> result = selectMaps(new QueryWrapper() + .select("SUM(payment_price) AS paymentPriceSum") + .eq("biz_id", bizId) + .eq("biz_type", bizType)); + // 获得数量 + if (CollUtil.isEmpty(result)) { + return BigDecimal.ZERO; + } + return BigDecimal.valueOf(MapUtil.getDouble(result.get(0), "paymentPriceSum", 0D)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentMapper.java new file mode 100644 index 000000000..5ad0cccfd --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentMapper.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.finance; + +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.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentItemDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * ERP 付款单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpFinancePaymentMapper extends BaseMapperX { + + default PageResult selectPage(ErpFinancePaymentPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .likeIfPresent(ErpFinancePaymentDO::getNo, reqVO.getNo()) + .betweenIfPresent(ErpFinancePaymentDO::getPaymentTime, reqVO.getPaymentTime()) + .eqIfPresent(ErpFinancePaymentDO::getSupplierId, reqVO.getSupplierId()) + .eqIfPresent(ErpFinancePaymentDO::getCreator, reqVO.getCreator()) + .eqIfPresent(ErpFinancePaymentDO::getFinanceUserId, reqVO.getFinanceUserId()) + .eqIfPresent(ErpFinancePaymentDO::getAccountId, reqVO.getAccountId()) + .eqIfPresent(ErpFinancePaymentDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpFinancePaymentDO::getRemark, reqVO.getRemark()) + .orderByDesc(ErpFinancePaymentDO::getId); + if (reqVO.getBizNo() != null) { + query.leftJoin(ErpFinancePaymentItemDO.class, ErpFinancePaymentItemDO::getPaymentId, ErpFinancePaymentDO::getId) + .eq(reqVO.getBizNo() != null, ErpFinancePaymentItemDO::getBizNo, reqVO.getBizNo()) + .groupBy(ErpFinancePaymentDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpFinancePaymentDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpFinancePaymentDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpFinancePaymentDO::getId, id).eq(ErpFinancePaymentDO::getStatus, status)); + } + + default ErpFinancePaymentDO selectByNo(String no) { + return selectOne(ErpFinancePaymentDO::getNo, no); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinanceReceiptItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinanceReceiptItemMapper.java new file mode 100644 index 000000000..cb6082b0e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinanceReceiptItemMapper.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.finance; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptItemDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * ERP 收款单项 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpFinanceReceiptItemMapper extends BaseMapperX { + + default List selectListByReceiptId(Long receiptId) { + return selectList(ErpFinanceReceiptItemDO::getReceiptId, receiptId); + } + + default List selectListByReceiptIds(Collection receiptIds) { + return selectList(ErpFinanceReceiptItemDO::getReceiptId, receiptIds); + } + + default BigDecimal selectReceiptPriceSumByBizIdAndBizType(Long bizId, Integer bizType) { + // SQL sum 查询 + List> result = selectMaps(new QueryWrapper() + .select("SUM(receipt_price) AS receiptPriceSum") + .eq("biz_id", bizId) + .eq("biz_type", bizType)); + // 获得数量 + if (CollUtil.isEmpty(result)) { + return BigDecimal.ZERO; + } + return BigDecimal.valueOf(MapUtil.getDouble(result.get(0), "receiptPriceSum", 0D)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinanceReceiptMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinanceReceiptMapper.java new file mode 100644 index 000000000..d895adea4 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinanceReceiptMapper.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.finance; + +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.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt.ErpFinanceReceiptPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptItemDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * ERP 收款单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpFinanceReceiptMapper extends BaseMapperX { + + default PageResult selectPage(ErpFinanceReceiptPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .likeIfPresent(ErpFinanceReceiptDO::getNo, reqVO.getNo()) + .betweenIfPresent(ErpFinanceReceiptDO::getReceiptTime, reqVO.getReceiptTime()) + .eqIfPresent(ErpFinanceReceiptDO::getCustomerId, reqVO.getCustomerId()) + .eqIfPresent(ErpFinanceReceiptDO::getCreator, reqVO.getCreator()) + .eqIfPresent(ErpFinanceReceiptDO::getFinanceUserId, reqVO.getFinanceUserId()) + .eqIfPresent(ErpFinanceReceiptDO::getAccountId, reqVO.getAccountId()) + .eqIfPresent(ErpFinanceReceiptDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpFinanceReceiptDO::getRemark, reqVO.getRemark()) + .orderByDesc(ErpFinanceReceiptDO::getId); + if (reqVO.getBizNo() != null) { + query.leftJoin(ErpFinanceReceiptItemDO.class, ErpFinanceReceiptItemDO::getReceiptId, ErpFinanceReceiptDO::getId) + .eq(reqVO.getBizNo() != null, ErpFinanceReceiptItemDO::getBizNo, reqVO.getBizNo()) + .groupBy(ErpFinanceReceiptDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpFinanceReceiptDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpFinanceReceiptDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpFinanceReceiptDO::getId, id).eq(ErpFinanceReceiptDO::getStatus, status)); + } + + default ErpFinanceReceiptDO selectByNo(String no) { + return selectOne(ErpFinanceReceiptDO::getNo, no); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductCategoryMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductCategoryMapper.java new file mode 100644 index 000000000..70bbc6429 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductCategoryMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.product; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryListReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * ERP 产品分类 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpProductCategoryMapper extends BaseMapperX { + + default List selectList(ErpProductCategoryListReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(ErpProductCategoryDO::getName, reqVO.getName()) + .eqIfPresent(ErpProductCategoryDO::getStatus, reqVO.getStatus()) + .orderByDesc(ErpProductCategoryDO::getId)); + } + + default ErpProductCategoryDO selectByParentIdAndName(Long parentId, String name) { + return selectOne(ErpProductCategoryDO::getParentId, parentId, ErpProductCategoryDO::getName, name); + } + + default Long selectCountByParentId(Long parentId) { + return selectCount(ErpProductCategoryDO::getParentId, parentId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java new file mode 100644 index 000000000..ff491fe22 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.product; + +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.erp.controller.admin.product.vo.product.ErpProductPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * ERP 产品 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpProductMapper extends BaseMapperX { + + default PageResult selectPage(ErpProductPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ErpProductDO::getName, reqVO.getName()) + .eqIfPresent(ErpProductDO::getCategoryId, reqVO.getCategoryId()) + .betweenIfPresent(ErpProductDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(ErpProductDO::getId)); + } + + default Long selectCountByCategoryId(Long categoryId) { + return selectCount(ErpProductDO::getCategoryId, categoryId); + } + + default Long selectCountByUnitId(Long unitId) { + return selectCount(ErpProductDO::getUnitId, unitId); + } + + default List selectListByStatus(Integer status) { + return selectList(ErpProductDO::getStatus, status); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductUnitMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductUnitMapper.java new file mode 100644 index 000000000..45db6a829 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductUnitMapper.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.product; + +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.erp.controller.admin.product.vo.unit.ErpProductUnitPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * ERP 产品单位 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpProductUnitMapper extends BaseMapperX { + + default PageResult selectPage(ErpProductUnitPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ErpProductUnitDO::getName, reqVO.getName()) + .eqIfPresent(ErpProductUnitDO::getStatus, reqVO.getStatus()) + .orderByDesc(ErpProductUnitDO::getId)); + } + + default ErpProductUnitDO selectByName(String name) { + return selectOne(ErpProductUnitDO::getName, name); + } + + default List selectListByStatus(Integer status) { + return selectList(ErpProductUnitDO::getStatus, status); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInItemMapper.java new file mode 100644 index 000000000..9140f9548 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInItemMapper.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.purchase; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInItemDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * ERP 采购入库项 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpPurchaseInItemMapper extends BaseMapperX { + + default List selectListByInId(Long inId) { + return selectList(ErpPurchaseInItemDO::getInId, inId); + } + + default List selectListByInIds(Collection inIds) { + return selectList(ErpPurchaseInItemDO::getInId, inIds); + } + + default int deleteByInId(Long inId) { + return delete(ErpPurchaseInItemDO::getInId, inId); + } + + /** + * 基于采购订单编号,查询每个采购订单项的入库数量之和 + * + * @param inIds 入库订单项编号数组 + * @return key:采购订单项编号;value:入库数量之和 + */ + default Map selectOrderItemCountSumMapByInIds(Collection inIds) { + if (CollUtil.isEmpty(inIds)) { + return Collections.emptyMap(); + } + // SQL sum 查询 + List> result = selectMaps(new QueryWrapper() + .select("order_item_id, SUM(count) AS sumCount") + .groupBy("order_item_id") + .in("in_id", inIds)); + // 获得数量 + return convertMap(result, obj -> (Long) obj.get("order_item_id"), obj -> (BigDecimal) obj.get("sumCount")); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInMapper.java new file mode 100644 index 000000000..c155d8cbe --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInMapper.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.purchase; + + +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.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in.ErpPurchaseInPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInItemDO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; +import java.util.Objects; + +/** + * ERP 采购入库 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpPurchaseInMapper extends BaseMapperX { + + default PageResult selectPage(ErpPurchaseInPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .likeIfPresent(ErpPurchaseInDO::getNo, reqVO.getNo()) + .eqIfPresent(ErpPurchaseInDO::getSupplierId, reqVO.getSupplierId()) + .betweenIfPresent(ErpPurchaseInDO::getInTime, reqVO.getInTime()) + .eqIfPresent(ErpPurchaseInDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpPurchaseInDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ErpPurchaseInDO::getCreator, reqVO.getCreator()) + .eqIfPresent(ErpPurchaseInDO::getAccountId, reqVO.getAccountId()) + .likeIfPresent(ErpPurchaseInDO::getOrderNo, reqVO.getOrderNo()) + .orderByDesc(ErpPurchaseInDO::getId); + // 付款状态。为什么需要 t. 的原因,是因为联表查询时,需要指定表名,不然会报字段不存在的错误 + if (Objects.equals(reqVO.getPaymentStatus(), ErpPurchaseInPageReqVO.PAYMENT_STATUS_NONE)) { + query.eq(ErpPurchaseInDO::getPaymentPrice, 0); + } else if (Objects.equals(reqVO.getPaymentStatus(), ErpPurchaseInPageReqVO.PAYMENT_STATUS_PART)) { + query.gt(ErpPurchaseInDO::getPaymentPrice, 0).apply("t.payment_price < t.total_price"); + } else if (Objects.equals(reqVO.getPaymentStatus(), ErpPurchaseInPageReqVO.PAYMENT_STATUS_ALL)) { + query.apply("t.payment_price = t.total_price"); + } + if (Boolean.TRUE.equals(reqVO.getPaymentEnable())) { + query.eq(ErpPurchaseInDO::getStatus, ErpAuditStatus.APPROVE.getStatus()) + .apply("t.payment_price < t.total_price"); + } + if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { + query.leftJoin(ErpPurchaseInItemDO.class, ErpPurchaseInItemDO::getInId, ErpPurchaseInDO::getId) + .eq(reqVO.getWarehouseId() != null, ErpPurchaseInItemDO::getWarehouseId, reqVO.getWarehouseId()) + .eq(reqVO.getProductId() != null, ErpPurchaseInItemDO::getProductId, reqVO.getProductId()) + .groupBy(ErpPurchaseInDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpPurchaseInDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpPurchaseInDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpPurchaseInDO::getId, id).eq(ErpPurchaseInDO::getStatus, status)); + } + + default ErpPurchaseInDO selectByNo(String no) { + return selectOne(ErpPurchaseInDO::getNo, no); + } + + default List selectListByOrderId(Long orderId) { + return selectList(ErpPurchaseInDO::getOrderId, orderId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderItemMapper.java new file mode 100644 index 000000000..17f1fe290 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderItemMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.purchase; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 采购订单明项目 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpPurchaseOrderItemMapper extends BaseMapperX { + + default List selectListByOrderId(Long orderId) { + return selectList(ErpPurchaseOrderItemDO::getOrderId, orderId); + } + + default List selectListByOrderIds(Collection orderIds) { + return selectList(ErpPurchaseOrderItemDO::getOrderId, orderIds); + } + + default int deleteByOrderId(Long orderId) { + return delete(ErpPurchaseOrderItemDO::getOrderId, orderId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderMapper.java new file mode 100644 index 000000000..01f0303f9 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderMapper.java @@ -0,0 +1,75 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.purchase; + +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.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Objects; + +/** + * ERP 采购订单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpPurchaseOrderMapper extends BaseMapperX { + + default PageResult selectPage(ErpPurchaseOrderPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .likeIfPresent(ErpPurchaseOrderDO::getNo, reqVO.getNo()) + .eqIfPresent(ErpPurchaseOrderDO::getSupplierId, reqVO.getSupplierId()) + .betweenIfPresent(ErpPurchaseOrderDO::getOrderTime, reqVO.getOrderTime()) + .eqIfPresent(ErpPurchaseOrderDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpPurchaseOrderDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ErpPurchaseOrderDO::getCreator, reqVO.getCreator()) + .orderByDesc(ErpPurchaseOrderDO::getId); + // 入库状态。为什么需要 t. 的原因,是因为联表查询时,需要指定表名,不然会报 in_count 错误 + if (Objects.equals(reqVO.getInStatus(), ErpPurchaseOrderPageReqVO.IN_STATUS_NONE)) { + query.eq(ErpPurchaseOrderDO::getInCount, 0); + } else if (Objects.equals(reqVO.getInStatus(), ErpPurchaseOrderPageReqVO.IN_STATUS_PART)) { + query.gt(ErpPurchaseOrderDO::getInCount, 0).apply("t.in_count < t.total_count"); + } else if (Objects.equals(reqVO.getInStatus(), ErpPurchaseOrderPageReqVO.IN_STATUS_ALL)) { + query.apply("t.in_count = t.total_count"); + } + // 退货状态 + if (Objects.equals(reqVO.getReturnStatus(), ErpPurchaseOrderPageReqVO.RETURN_STATUS_NONE)) { + query.eq(ErpPurchaseOrderDO::getReturnCount, 0); + } else if (Objects.equals(reqVO.getReturnStatus(), ErpPurchaseOrderPageReqVO.RETURN_STATUS_PART)) { + query.gt(ErpPurchaseOrderDO::getReturnCount, 0).apply("t.return_count < t.total_count"); + } else if (Objects.equals(reqVO.getReturnStatus(), ErpPurchaseOrderPageReqVO.RETURN_STATUS_ALL)) { + query.apply("t.return_count = t.total_count"); + } + // 可采购入库 + if (Boolean.TRUE.equals(reqVO.getInEnable())) { + query.eq(ErpPurchaseOrderDO::getStatus, ErpAuditStatus.APPROVE.getStatus()) + .apply("t.in_count < t.total_count"); + } + // 可采购退货 + if (Boolean.TRUE.equals(reqVO.getReturnEnable())) { + query.eq(ErpPurchaseOrderDO::getStatus, ErpAuditStatus.APPROVE.getStatus()) + .apply("t.return_count < t.in_count"); + } + if (reqVO.getProductId() != null) { + query.leftJoin(ErpPurchaseOrderItemDO.class, ErpPurchaseOrderItemDO::getOrderId, ErpPurchaseOrderDO::getId) + .eq(reqVO.getProductId() != null, ErpPurchaseOrderItemDO::getProductId, reqVO.getProductId()) + .groupBy(ErpPurchaseOrderDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpPurchaseOrderDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpPurchaseOrderDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpPurchaseOrderDO::getId, id).eq(ErpPurchaseOrderDO::getStatus, status)); + } + + default ErpPurchaseOrderDO selectByNo(String no) { + return selectOne(ErpPurchaseOrderDO::getNo, no); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnItemMapper.java new file mode 100644 index 000000000..2a8011900 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnItemMapper.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.purchase; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnItemDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * ERP 采购退货项 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpPurchaseReturnItemMapper extends BaseMapperX { + + default List selectListByReturnId(Long returnId) { + return selectList(ErpPurchaseReturnItemDO::getReturnId, returnId); + } + + default List selectListByReturnIds(Collection returnIds) { + return selectList(ErpPurchaseReturnItemDO::getReturnId, returnIds); + } + + default int deleteByReturnId(Long returnId) { + return delete(ErpPurchaseReturnItemDO::getReturnId, returnId); + } + + /** + * 基于采购订单编号,查询每个采购订单项的退货数量之和 + * + * @param returnIds 入库订单项编号数组 + * @return key:采购订单项编号;value:退货数量之和 + */ + default Map selectOrderItemCountSumMapByReturnIds(Collection returnIds) { + if (CollUtil.isEmpty(returnIds)) { + return Collections.emptyMap(); + } + // SQL sum 查询 + List> result = selectMaps(new QueryWrapper() + .select("order_item_id, SUM(count) AS sumCount") + .groupBy("order_item_id") + .in("return_id", returnIds)); + // 获得数量 + return convertMap(result, obj -> (Long) obj.get("order_item_id"), obj -> (BigDecimal) obj.get("sumCount")); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnMapper.java new file mode 100644 index 000000000..689a55dfd --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnMapper.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.purchase; + +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.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns.ErpPurchaseReturnPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnItemDO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; +import java.util.Objects; + +/** + * ERP 采购退货 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpPurchaseReturnMapper extends BaseMapperX { + + default PageResult selectPage(ErpPurchaseReturnPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .likeIfPresent(ErpPurchaseReturnDO::getNo, reqVO.getNo()) + .eqIfPresent(ErpPurchaseReturnDO::getSupplierId, reqVO.getSupplierId()) + .betweenIfPresent(ErpPurchaseReturnDO::getReturnTime, reqVO.getReturnTime()) + .eqIfPresent(ErpPurchaseReturnDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpPurchaseReturnDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ErpPurchaseReturnDO::getCreator, reqVO.getCreator()) + .eqIfPresent(ErpPurchaseReturnDO::getAccountId, reqVO.getAccountId()) + .likeIfPresent(ErpPurchaseReturnDO::getOrderNo, reqVO.getOrderNo()) + .orderByDesc(ErpPurchaseReturnDO::getId); + // 退款状态。为什么需要 t. 的原因,是因为联表查询时,需要指定表名,不然会报字段不存在的错误 + if (Objects.equals(reqVO.getRefundStatus(), ErpPurchaseReturnPageReqVO.REFUND_STATUS_NONE)) { + query.eq(ErpPurchaseReturnDO::getRefundPrice, 0); + } else if (Objects.equals(reqVO.getRefundStatus(), ErpPurchaseReturnPageReqVO.REFUND_STATUS_PART)) { + query.gt(ErpPurchaseReturnDO::getRefundPrice, 0).apply("t.refund_price < t.total_price"); + } else if (Objects.equals(reqVO.getRefundStatus(), ErpPurchaseReturnPageReqVO.REFUND_STATUS_ALL)) { + query.apply("t.refund_price = t.total_price"); + } + if (Boolean.TRUE.equals(reqVO.getRefundEnable())) { + query.eq(ErpPurchaseInDO::getStatus, ErpAuditStatus.APPROVE.getStatus()) + .apply("t.refund_price < t.total_price"); + } + if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { + query.leftJoin(ErpPurchaseReturnItemDO.class, ErpPurchaseReturnItemDO::getReturnId, ErpPurchaseReturnDO::getId) + .eq(reqVO.getWarehouseId() != null, ErpPurchaseReturnItemDO::getWarehouseId, reqVO.getWarehouseId()) + .eq(reqVO.getProductId() != null, ErpPurchaseReturnItemDO::getProductId, reqVO.getProductId()) + .groupBy(ErpPurchaseReturnDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpPurchaseReturnDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpPurchaseReturnDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpPurchaseReturnDO::getId, id).eq(ErpPurchaseReturnDO::getStatus, status)); + } + + default ErpPurchaseReturnDO selectByNo(String no) { + return selectOne(ErpPurchaseReturnDO::getNo, no); + } + + default List selectListByOrderId(Long orderId) { + return selectList(ErpPurchaseReturnDO::getOrderId, orderId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpSupplierMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpSupplierMapper.java new file mode 100644 index 000000000..c74f1e6f8 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpSupplierMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.purchase; + +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.erp.controller.admin.purchase.vo.supplier.ErpSupplierPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * ERP 供应商 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpSupplierMapper extends BaseMapperX { + + default PageResult selectPage(ErpSupplierPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ErpSupplierDO::getName, reqVO.getName()) + .likeIfPresent(ErpSupplierDO::getMobile, reqVO.getMobile()) + .likeIfPresent(ErpSupplierDO::getTelephone, reqVO.getTelephone()) + .orderByDesc(ErpSupplierDO::getId)); + } + + default List selectListByStatus(Integer status) { + return selectList(ErpSupplierDO::getStatus, status); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpCustomerMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpCustomerMapper.java new file mode 100644 index 000000000..4970f9ad5 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpCustomerMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.sale; + +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.erp.controller.admin.sale.vo.customer.ErpCustomerPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * ERP 客户 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpCustomerMapper extends BaseMapperX { + + default PageResult selectPage(ErpCustomerPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ErpCustomerDO::getName, reqVO.getName()) + .eqIfPresent(ErpCustomerDO::getMobile, reqVO.getMobile()) + .eqIfPresent(ErpCustomerDO::getTelephone, reqVO.getTelephone()) + .orderByDesc(ErpCustomerDO::getId)); + } + + default List selectListByStatus(Integer status) { + return selectList(ErpCustomerDO::getStatus, status); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderItemMapper.java new file mode 100644 index 000000000..d2825e563 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderItemMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.sale; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 销售订单明项目 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpSaleOrderItemMapper extends BaseMapperX { + + default List selectListByOrderId(Long orderId) { + return selectList(ErpSaleOrderItemDO::getOrderId, orderId); + } + + default List selectListByOrderIds(Collection orderIds) { + return selectList(ErpSaleOrderItemDO::getOrderId, orderIds); + } + + default int deleteByOrderId(Long orderId) { + return delete(ErpSaleOrderItemDO::getOrderId, orderId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java new file mode 100644 index 000000000..8ed3b6fcd --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.sale; + + +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.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderItemDO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Objects; + +/** + * ERP 销售订单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpSaleOrderMapper extends BaseMapperX { + + default PageResult selectPage(ErpSaleOrderPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .likeIfPresent(ErpSaleOrderDO::getNo, reqVO.getNo()) + .eqIfPresent(ErpSaleOrderDO::getCustomerId, reqVO.getCustomerId()) + .betweenIfPresent(ErpSaleOrderDO::getOrderTime, reqVO.getOrderTime()) + .eqIfPresent(ErpSaleOrderDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpSaleOrderDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ErpSaleOrderDO::getCreator, reqVO.getCreator()) + .orderByDesc(ErpSaleOrderDO::getId); + // 入库状态。为什么需要 t. 的原因,是因为联表查询时,需要指定表名,不然会报 out_count 错误 + if (Objects.equals(reqVO.getOutStatus(), ErpSaleOrderPageReqVO.OUT_STATUS_NONE)) { + query.eq(ErpSaleOrderDO::getOutCount, 0); + } else if (Objects.equals(reqVO.getOutStatus(), ErpSaleOrderPageReqVO.OUT_STATUS_PART)) { + query.gt(ErpSaleOrderDO::getOutCount, 0).apply("t.out_count < t.total_count"); + } else if (Objects.equals(reqVO.getOutStatus(), ErpSaleOrderPageReqVO.OUT_STATUS_ALL)) { + query.apply("t.out_count = t.total_count"); + } + // 退货状态 + if (Objects.equals(reqVO.getReturnStatus(), ErpSaleOrderPageReqVO.RETURN_STATUS_NONE)) { + query.eq(ErpSaleOrderDO::getReturnCount, 0); + } else if (Objects.equals(reqVO.getReturnStatus(), ErpSaleOrderPageReqVO.RETURN_STATUS_PART)) { + query.gt(ErpSaleOrderDO::getReturnCount, 0).apply("t.return_count < t.total_count"); + } else if (Objects.equals(reqVO.getReturnStatus(), ErpSaleOrderPageReqVO.RETURN_STATUS_ALL)) { + query.apply("t.return_count = t.total_count"); + } + // 可销售出库 + if (Boolean.TRUE.equals(reqVO.getOutEnable())) { + query.eq(ErpSaleOrderDO::getStatus, ErpAuditStatus.APPROVE.getStatus()) + .apply("t.out_count < t.total_count"); + } + // 可销售退货 + if (Boolean.TRUE.equals(reqVO.getReturnEnable())) { + query.eq(ErpSaleOrderDO::getStatus, ErpAuditStatus.APPROVE.getStatus()) + .apply("t.return_count < t.out_count"); + } + if (reqVO.getProductId() != null) { + query.leftJoin(ErpSaleOrderItemDO.class, ErpSaleOrderItemDO::getOrderId, ErpSaleOrderDO::getId) + .eq(reqVO.getProductId() != null, ErpSaleOrderItemDO::getProductId, reqVO.getProductId()) + .groupBy(ErpSaleOrderDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpSaleOrderDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpSaleOrderDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpSaleOrderDO::getId, id).eq(ErpSaleOrderDO::getStatus, status)); + } + + default ErpSaleOrderDO selectByNo(String no) { + return selectOne(ErpSaleOrderDO::getNo, no); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutItemMapper.java new file mode 100644 index 000000000..9cd5dede0 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutItemMapper.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.sale; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutItemDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * ERP 销售出库项 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpSaleOutItemMapper extends BaseMapperX { + + default List selectListByOutId(Long outId) { + return selectList(ErpSaleOutItemDO::getOutId, outId); + } + + default List selectListByOutIds(Collection outIds) { + return selectList(ErpSaleOutItemDO::getOutId, outIds); + } + + default int deleteByOutId(Long outId) { + return delete(ErpSaleOutItemDO::getOutId, outId); + } + + /** + * 基于销售订单编号,查询每个销售订单项的出库数量之和 + * + * @param outIds 出库订单项编号数组 + * @return key:销售订单项编号;value:出库数量之和 + */ + default Map selectOrderItemCountSumMapByOutIds(Collection outIds) { + if (CollUtil.isEmpty(outIds)) { + return Collections.emptyMap(); + } + // SQL sum 查询 + List> result = selectMaps(new QueryWrapper() + .select("order_item_id, SUM(count) AS sumCount") + .groupBy("order_item_id") + .in("out_id", outIds)); + // 获得数量 + return convertMap(result, obj -> (Long) obj.get("order_item_id"), obj -> (BigDecimal) obj.get("sumCount")); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java new file mode 100644 index 000000000..128913fcd --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.sale; + + +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.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out.ErpSaleOutPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutItemDO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; +import java.util.Objects; + +/** + * ERP 销售出库 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpSaleOutMapper extends BaseMapperX { + + default PageResult selectPage(ErpSaleOutPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .likeIfPresent(ErpSaleOutDO::getNo, reqVO.getNo()) + .eqIfPresent(ErpSaleOutDO::getCustomerId, reqVO.getCustomerId()) + .betweenIfPresent(ErpSaleOutDO::getOutTime, reqVO.getOutTime()) + .eqIfPresent(ErpSaleOutDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpSaleOutDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ErpSaleOutDO::getCreator, reqVO.getCreator()) + .eqIfPresent(ErpSaleOutDO::getAccountId, reqVO.getAccountId()) + .likeIfPresent(ErpSaleOutDO::getOrderNo, reqVO.getOrderNo()) + .orderByDesc(ErpSaleOutDO::getId); + // 收款状态。为什么需要 t. 的原因,是因为联表查询时,需要指定表名,不然会报字段不存在的错误 + if (Objects.equals(reqVO.getReceiptStatus(), ErpSaleOutPageReqVO.RECEIPT_STATUS_NONE)) { + query.eq(ErpSaleOutDO::getReceiptPrice, 0); + } else if (Objects.equals(reqVO.getReceiptStatus(), ErpSaleOutPageReqVO.RECEIPT_STATUS_PART)) { + query.gt(ErpSaleOutDO::getReceiptPrice, 0).apply("t.receipt_price < t.total_price"); + } else if (Objects.equals(reqVO.getReceiptStatus(), ErpSaleOutPageReqVO.RECEIPT_STATUS_ALL)) { + query.apply("t.receipt_price = t.total_price"); + } + if (Boolean.TRUE.equals(reqVO.getReceiptEnable())) { + query.eq(ErpSaleOutDO::getStatus, ErpAuditStatus.APPROVE.getStatus()) + .apply("t.receipt_price < t.total_price"); + } + if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { + query.leftJoin(ErpSaleOutItemDO.class, ErpSaleOutItemDO::getOutId, ErpSaleOutDO::getId) + .eq(reqVO.getWarehouseId() != null, ErpSaleOutItemDO::getWarehouseId, reqVO.getWarehouseId()) + .eq(reqVO.getProductId() != null, ErpSaleOutItemDO::getProductId, reqVO.getProductId()) + .groupBy(ErpSaleOutDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpSaleOutDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpSaleOutDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpSaleOutDO::getId, id).eq(ErpSaleOutDO::getStatus, status)); + } + + default ErpSaleOutDO selectByNo(String no) { + return selectOne(ErpSaleOutDO::getNo, no); + } + + default List selectListByOrderId(Long orderId) { + return selectList(ErpSaleOutDO::getOrderId, orderId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnItemMapper.java new file mode 100644 index 000000000..fdc572964 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnItemMapper.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.sale; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnItemDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * ERP 销售退货项 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpSaleReturnItemMapper extends BaseMapperX { + + default List selectListByReturnId(Long returnId) { + return selectList(ErpSaleReturnItemDO::getReturnId, returnId); + } + + default List selectListByReturnIds(Collection returnIds) { + return selectList(ErpSaleReturnItemDO::getReturnId, returnIds); + } + + default int deleteByReturnId(Long returnId) { + return delete(ErpSaleReturnItemDO::getReturnId, returnId); + } + + /** + * 基于销售订单编号,查询每个销售订单项的退货数量之和 + * + * @param returnIds 出库订单项编号数组 + * @return key:销售订单项编号;value:退货数量之和 + */ + default Map selectOrderItemCountSumMapByReturnIds(Collection returnIds) { + if (CollUtil.isEmpty(returnIds)) { + return Collections.emptyMap(); + } + // SQL sum 查询 + List> result = selectMaps(new QueryWrapper() + .select("order_item_id, SUM(count) AS sumCount") + .groupBy("order_item_id") + .in("return_id", returnIds)); + // 获得数量 + return convertMap(result, obj -> (Long) obj.get("order_item_id"), obj -> (BigDecimal) obj.get("sumCount")); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnMapper.java new file mode 100644 index 000000000..867b45499 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnMapper.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.sale; + + +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.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns.ErpSaleReturnPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnItemDO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; +import java.util.Objects; + +/** + * ERP 销售退货 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpSaleReturnMapper extends BaseMapperX { + + default PageResult selectPage(ErpSaleReturnPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .likeIfPresent(ErpSaleReturnDO::getNo, reqVO.getNo()) + .eqIfPresent(ErpSaleReturnDO::getCustomerId, reqVO.getCustomerId()) + .betweenIfPresent(ErpSaleReturnDO::getReturnTime, reqVO.getReturnTime()) + .eqIfPresent(ErpSaleReturnDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpSaleReturnDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ErpSaleReturnDO::getCreator, reqVO.getCreator()) + .eqIfPresent(ErpSaleReturnDO::getAccountId, reqVO.getAccountId()) + .likeIfPresent(ErpSaleReturnDO::getOrderNo, reqVO.getOrderNo()) + .orderByDesc(ErpSaleReturnDO::getId); + // 退款状态。为什么需要 t. 的原因,是因为联表查询时,需要指定表名,不然会报字段不存在的错误 + if (Objects.equals(reqVO.getRefundStatus(), ErpSaleReturnPageReqVO.REFUND_STATUS_NONE)) { + query.eq(ErpSaleReturnDO::getRefundPrice, 0); + } else if (Objects.equals(reqVO.getRefundStatus(), ErpSaleReturnPageReqVO.REFUND_STATUS_PART)) { + query.gt(ErpSaleReturnDO::getRefundPrice, 0).apply("t.refund_price < t.total_price"); + } else if (Objects.equals(reqVO.getRefundStatus(), ErpSaleReturnPageReqVO.REFUND_STATUS_ALL)) { + query.apply("t.refund_price = t.total_price"); + } + if (Boolean.TRUE.equals(reqVO.getRefundEnable())) { + query.eq(ErpSaleOutDO::getStatus, ErpAuditStatus.APPROVE.getStatus()) + .apply("t.refund_price < t.total_price"); + } + if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { + query.leftJoin(ErpSaleReturnItemDO.class, ErpSaleReturnItemDO::getReturnId, ErpSaleReturnDO::getId) + .eq(reqVO.getWarehouseId() != null, ErpSaleReturnItemDO::getWarehouseId, reqVO.getWarehouseId()) + .eq(reqVO.getProductId() != null, ErpSaleReturnItemDO::getProductId, reqVO.getProductId()) + .groupBy(ErpSaleReturnDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpSaleReturnDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpSaleReturnDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpSaleReturnDO::getId, id).eq(ErpSaleReturnDO::getStatus, status)); + } + + default ErpSaleReturnDO selectByNo(String no) { + return selectOne(ErpSaleReturnDO::getNo, no); + } + + default List selectListByOrderId(Long orderId) { + return selectList(ErpSaleReturnDO::getOrderId, orderId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckItemMapper.java new file mode 100644 index 000000000..ae13f9f96 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckItemMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 库存盘点单项 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpStockCheckItemMapper extends BaseMapperX { + + default List selectListByCheckId(Long checkId) { + return selectList(ErpStockCheckItemDO::getCheckId, checkId); + } + + default List selectListByCheckIds(Collection checkIds) { + return selectList(ErpStockCheckItemDO::getCheckId, checkIds); + } + + default int deleteByCheckId(Long checkId) { + return delete(ErpStockCheckItemDO::getCheckId, checkId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckMapper.java new file mode 100644 index 000000000..dd976df3d --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckMapper.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +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.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckItemDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * ERP 库存调拨单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpStockCheckMapper extends BaseMapperX { + + default PageResult selectPage(ErpStockCheckPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .likeIfPresent(ErpStockCheckDO::getNo, reqVO.getNo()) + .betweenIfPresent(ErpStockCheckDO::getCheckTime, reqVO.getCheckTime()) + .eqIfPresent(ErpStockCheckDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpStockCheckDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ErpStockCheckDO::getCreator, reqVO.getCreator()) + .orderByDesc(ErpStockCheckDO::getId); + if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { + query.leftJoin(ErpStockCheckItemDO.class, ErpStockCheckItemDO::getCheckId, ErpStockCheckDO::getId) + .eq(reqVO.getWarehouseId() != null, ErpStockCheckItemDO::getWarehouseId, reqVO.getWarehouseId()) + .eq(reqVO.getProductId() != null, ErpStockCheckItemDO::getProductId, reqVO.getProductId()) + .groupBy(ErpStockCheckDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpStockCheckDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpStockCheckDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpStockCheckDO::getId, id).eq(ErpStockCheckDO::getStatus, status)); + } + + default ErpStockCheckDO selectByNo(String no) { + return selectOne(ErpStockCheckDO::getNo, no); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInItemMapper.java new file mode 100644 index 000000000..2731aa7bb --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInItemMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 其它入库单项 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpStockInItemMapper extends BaseMapperX { + + default List selectListByInId(Long inId) { + return selectList(ErpStockInItemDO::getInId, inId); + } + + default List selectListByInIds(Collection inIds) { + return selectList(ErpStockInItemDO::getInId, inIds); + } + + default int deleteByInId(Long inId) { + return delete(ErpStockInItemDO::getInId, inId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java new file mode 100644 index 000000000..e815583ac --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +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.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * ERP 其它入库单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpStockInMapper extends BaseMapperX { + + default PageResult selectPage(ErpStockInPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .likeIfPresent(ErpStockInDO::getNo, reqVO.getNo()) + .eqIfPresent(ErpStockInDO::getSupplierId, reqVO.getSupplierId()) + .betweenIfPresent(ErpStockInDO::getInTime, reqVO.getInTime()) + .eqIfPresent(ErpStockInDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpStockInDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ErpStockInDO::getCreator, reqVO.getCreator()) + .orderByDesc(ErpStockInDO::getId); + if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { + query.leftJoin(ErpStockInItemDO.class, ErpStockInItemDO::getInId, ErpStockInDO::getId) + .eq(reqVO.getWarehouseId() != null, ErpStockInItemDO::getWarehouseId, reqVO.getWarehouseId()) + .eq(reqVO.getProductId() != null, ErpStockInItemDO::getProductId, reqVO.getProductId()) + .groupBy(ErpStockInDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpStockInDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpStockInDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpStockInDO::getId, id).eq(ErpStockInDO::getStatus, status)); + } + + default ErpStockInDO selectByNo(String no) { + return selectOne(ErpStockInDO::getNo, no); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java new file mode 100644 index 000000000..0ebc98597 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; +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.erp.controller.admin.stock.vo.stock.ErpStockPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +/** + * ERP 产品库存 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpStockMapper extends BaseMapperX { + + default PageResult selectPage(ErpStockPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(ErpStockDO::getProductId, reqVO.getProductId()) + .eqIfPresent(ErpStockDO::getWarehouseId, reqVO.getWarehouseId()) + .orderByDesc(ErpStockDO::getId)); + } + + default ErpStockDO selectByProductIdAndWarehouseId(Long productId, Long warehouseId) { + return selectOne(ErpStockDO::getProductId, productId, + ErpStockDO::getWarehouseId, warehouseId); + } + + default int updateCountIncrement(Long id, BigDecimal count, boolean negativeEnable) { + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper() + .eq(ErpStockDO::getId, id); + if (count.compareTo(BigDecimal.ZERO) > 0) { + updateWrapper.setSql("count = count + " + count); + } else if (count.compareTo(BigDecimal.ZERO) < 0) { + if (!negativeEnable) { + updateWrapper.ge(ErpStockDO::getCount, count.abs()); + } + updateWrapper.setSql("count = count - " + count.abs()); + } + return update(null, updateWrapper); + } + + default BigDecimal selectSumByProductId(Long productId) { + // SQL sum 查询 + List> result = selectMaps(new QueryWrapper() + .select("SUM(count) AS sumCount") + .eq("product_id", productId)); + // 获得数量 + if (CollUtil.isEmpty(result)) { + return BigDecimal.ZERO; + } + return BigDecimal.valueOf(MapUtil.getDouble(result.get(0), "sumCount", 0D)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMoveItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMoveItemMapper.java new file mode 100644 index 000000000..21a267029 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMoveItemMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 库存调拨单项 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpStockMoveItemMapper extends BaseMapperX { + + default List selectListByMoveId(Long moveId) { + return selectList(ErpStockMoveItemDO::getMoveId, moveId); + } + + default List selectListByMoveIds(Collection moveIds) { + return selectList(ErpStockMoveItemDO::getMoveId, moveIds); + } + + default int deleteByMoveId(Long moveId) { + return delete(ErpStockMoveItemDO::getMoveId, moveId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMoveMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMoveMapper.java new file mode 100644 index 000000000..9a8ce0b64 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMoveMapper.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +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.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMovePageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveItemDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * ERP 库存调拨单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpStockMoveMapper extends BaseMapperX { + + default PageResult selectPage(ErpStockMovePageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .likeIfPresent(ErpStockMoveDO::getNo, reqVO.getNo()) + .betweenIfPresent(ErpStockMoveDO::getMoveTime, reqVO.getMoveTime()) + .eqIfPresent(ErpStockMoveDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpStockMoveDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ErpStockMoveDO::getCreator, reqVO.getCreator()) + .orderByDesc(ErpStockMoveDO::getId); + if (reqVO.getFromWarehouseId() != null || reqVO.getProductId() != null) { + query.leftJoin(ErpStockMoveItemDO.class, ErpStockMoveItemDO::getMoveId, ErpStockMoveDO::getId) + .eq(reqVO.getFromWarehouseId() != null, ErpStockMoveItemDO::getFromWarehouseId, reqVO.getFromWarehouseId()) + .eq(reqVO.getProductId() != null, ErpStockMoveItemDO::getProductId, reqVO.getProductId()) + .groupBy(ErpStockMoveDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpStockMoveDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpStockMoveDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpStockMoveDO::getId, id).eq(ErpStockMoveDO::getStatus, status)); + } + + default ErpStockMoveDO selectByNo(String no) { + return selectOne(ErpStockMoveDO::getNo, no); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutItemMapper.java new file mode 100644 index 000000000..3b27cd3dc --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutItemMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 其它出库单项 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpStockOutItemMapper extends BaseMapperX { + + default List selectListByOutId(Long outId) { + return selectList(ErpStockOutItemDO::getOutId, outId); + } + + default List selectListByOutIds(Collection outIds) { + return selectList(ErpStockOutItemDO::getOutId, outIds); + } + + default int deleteByOutId(Long outId) { + return delete(ErpStockOutItemDO::getOutId, outId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutMapper.java new file mode 100644 index 000000000..a73dd3ccf --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutMapper.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +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.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * ERP 其它出库单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpStockOutMapper extends BaseMapperX { + + default PageResult selectPage(ErpStockOutPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .likeIfPresent(ErpStockOutDO::getNo, reqVO.getNo()) + .eqIfPresent(ErpStockOutDO::getCustomerId, reqVO.getCustomerId()) + .betweenIfPresent(ErpStockOutDO::getOutTime, reqVO.getOutTime()) + .eqIfPresent(ErpStockOutDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpStockOutDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ErpStockOutDO::getCreator, reqVO.getCreator()) + .orderByDesc(ErpStockOutDO::getId); + if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { + query.leftJoin(ErpStockOutItemDO.class, ErpStockOutItemDO::getOutId, ErpStockOutDO::getId) + .eq(reqVO.getWarehouseId() != null, ErpStockOutItemDO::getWarehouseId, reqVO.getWarehouseId()) + .eq(reqVO.getProductId() != null, ErpStockOutItemDO::getProductId, reqVO.getProductId()) + .groupBy(ErpStockOutDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpStockOutDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpStockOutDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpStockOutDO::getId, id).eq(ErpStockOutDO::getStatus, status)); + } + + default ErpStockOutDO selectByNo(String no) { + return selectOne(ErpStockOutDO::getNo, no); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockRecordMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockRecordMapper.java new file mode 100644 index 000000000..bfd8b6751 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockRecordMapper.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +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.erp.controller.admin.stock.vo.record.ErpStockRecordPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * ERP 产品库存明细 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpStockRecordMapper extends BaseMapperX { + + default PageResult selectPage(ErpStockRecordPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(ErpStockRecordDO::getProductId, reqVO.getProductId()) + .eqIfPresent(ErpStockRecordDO::getWarehouseId, reqVO.getWarehouseId()) + .eqIfPresent(ErpStockRecordDO::getBizType, reqVO.getBizType()) + .likeIfPresent(ErpStockRecordDO::getBizNo, reqVO.getBizNo()) + .betweenIfPresent(ErpStockRecordDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(ErpStockRecordDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpWarehouseMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpWarehouseMapper.java new file mode 100644 index 000000000..0442011f2 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpWarehouseMapper.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +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.erp.controller.admin.stock.vo.warehouse.ErpWarehousePageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * ERP 仓库 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpWarehouseMapper extends BaseMapperX { + + default PageResult selectPage(ErpWarehousePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ErpWarehouseDO::getName, reqVO.getName()) + .eqIfPresent(ErpWarehouseDO::getStatus, reqVO.getStatus()) + .orderByDesc(ErpWarehouseDO::getId)); + } + + default ErpWarehouseDO selectByDefaultStatus() { + return selectOne(ErpWarehouseDO::getDefaultStatus, true); + } + + default List selectListByStatus(Integer status) { + return selectList(ErpWarehouseDO::getStatus, status); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/RedisKeyConstants.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/RedisKeyConstants.java new file mode 100644 index 000000000..f0ba46807 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/RedisKeyConstants.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.erp.dal.redis; + +/** + * ERP Redis Key 枚举类 + * + * @author 芋道源码 + */ +public interface RedisKeyConstants { + + /** + * 序号的缓存 + * + * KEY 格式:trade_no:{prefix} + * VALUE 数据格式:编号自增 + */ + String NO = "seq_no:"; + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java new file mode 100644 index 000000000..8214cf13d --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java @@ -0,0 +1,96 @@ +package cn.iocoder.yudao.module.erp.dal.redis.no; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import cn.iocoder.yudao.module.erp.dal.redis.RedisKeyConstants; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Repository; + +import javax.annotation.Resource; +import java.time.Duration; +import java.time.LocalDateTime; + + +/** + * 订单序号的 Redis DAO + * + * @author HUIHUI + */ +@Repository +public class ErpNoRedisDAO { + + /** + * 其它入库 {@link cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO} + */ + public static final String STOCK_IN_NO_PREFIX = "QTRK"; + /** + * 其它出库 {@link cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO} + */ + public static final String STOCK_OUT_NO_PREFIX = "QCKD"; + + /** + * 库存调拨 {@link cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveDO} + */ + public static final String STOCK_MOVE_NO_PREFIX = "QCDB"; + + /** + * 库存盘点 {@link cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckDO} + */ + public static final String STOCK_CHECK_NO_PREFIX = "QCPD"; + + /** + * 销售订单 {@link cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO} + */ + public static final String SALE_ORDER_NO_PREFIX = "XSDD"; + /** + * 销售出库 {@link cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutDO} + */ + public static final String SALE_OUT_NO_PREFIX = "XSCK"; + /** + * 销售退货 {@link cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnDO} + */ + public static final String SALE_RETURN_NO_PREFIX = "XSTH"; + + /** + * 采购订单 {@link cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO} + */ + public static final String PURCHASE_ORDER_NO_PREFIX = "CGDD"; + /** + * 采购入库 {@link cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO} + */ + public static final String PURCHASE_IN_NO_PREFIX = "CGRK"; + /** + * 采购退货 {@link cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnDO} + */ + public static final String PURCHASE_RETURN_NO_PREFIX = "CGTH"; + + /** + * 付款单 {@link cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO} + */ + public static final String FINANCE_PAYMENT_NO_PREFIX = "FKD"; + /** + * 收款单 {@link cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptDO} + */ + public static final String FINANCE_RECEIPT_NO_PREFIX = "SKD"; + + @Resource + private StringRedisTemplate stringRedisTemplate; + + /** + * 生成序号,使用当前日期,格式为 {PREFIX} + yyyyMMdd + 6 位自增 + * 例如说:QTRK 202109 000001 (没有中间空格) + * + * @param prefix 前缀 + * @return 序号 + */ + public String generate(String prefix) { + // 递增序号 + String noPrefix = prefix + DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATE_PATTERN); + String key = RedisKeyConstants.NO + noPrefix; + Long no = stringRedisTemplate.opsForValue().increment(key); + // 设置过期时间 + stringRedisTemplate.expire(key, Duration.ofDays(1L)); + return noPrefix + String.format("%06d", no); + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/package-info.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/package-info.java new file mode 100644 index 000000000..af7bc123c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/package-info.java @@ -0,0 +1,6 @@ +/** + * 属于 erp 模块的 framework 封装 + * + * @author 芋道源码 + */ +package cn.iocoder.yudao.module.erp.framework; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/web/config/ErpWebConfiguration.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/web/config/ErpWebConfiguration.java new file mode 100644 index 000000000..5d866a1b9 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/web/config/ErpWebConfiguration.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.erp.framework.web.config; + +import cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration; +import org.springdoc.core.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * erp 模块的 web 组件的 Configuration + * + * @author 芋道源码 + */ +@Configuration(proxyBeanMethods = false) +public class ErpWebConfiguration { + + /** + * erp 模块的 API 分组 + */ + @Bean + public GroupedOpenApi erpGroupedOpenApi() { + return YudaoSwaggerAutoConfiguration.buildGroupedOpenApi("erp"); + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/web/package-info.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/web/package-info.java new file mode 100644 index 000000000..70f70c035 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/web/package-info.java @@ -0,0 +1,4 @@ +/** + * trade 模块的 web 配置 + */ +package cn.iocoder.yudao.module.erp.framework.web; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/package-info.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/package-info.java new file mode 100644 index 000000000..2608a9889 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/package-info.java @@ -0,0 +1,10 @@ +/** + * erp 包下,企业资源管理(Enterprise Resource Planning)。 + * 例如说:采购、销售、库存、财务、产品等等 + * + * 1. Controller URL:以 /erp/ 开头,避免和其它 Module 冲突 + * 2. DataObject 表名:以 erp_ 开头,方便在数据库中区分 + * + * 注意,由于 Erp 模块下,容易和其它模块重名,所以类名都加载 Erp 的前缀~ + */ +package cn.iocoder.yudao.module.erp; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java new file mode 100644 index 000000000..9226e15c6 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.erp.service.finance; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * ERP 结算账户 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpAccountService { + + /** + * 创建结算账户 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createAccount(@Valid ErpAccountSaveReqVO createReqVO); + + /** + * 更新ERP 结算账户 + * + * @param updateReqVO 更新信息 + */ + void updateAccount(@Valid ErpAccountSaveReqVO updateReqVO); + + /** + * 更新结算账户默认状态 + * + * @param id 编号 + * @param defaultStatus 默认状态 + */ + void updateAccountDefaultStatus(Long id, Boolean defaultStatus); + + /** + * 删除结算账户 + * + * @param id 编号 + */ + void deleteAccount(Long id); + + /** + * 获得结算账户 + * + * @param id 编号 + * @return 结算账户 + */ + ErpAccountDO getAccount(Long id); + + /** + * 校验结算账户 + * + * @param id 编号 + * @return 结算账户 + */ + ErpAccountDO validateAccount(Long id); + + /** + * 获得指定状态的结算账户列表 + * + * @param status 状态 + * @return 结算账户 + */ + List getAccountListByStatus(Integer status); + + /** + * 获得结算账户列表 + * + * @param ids 编号数组 + * @return 结算账户列表 + */ + List getAccountList(Collection ids); + + /** + * 获得结算账户 Map + * + * @param ids 编号数组 + * @return 结算账户 Map + */ + default Map getAccountMap(Collection ids) { + return convertMap(getAccountList(ids), ErpAccountDO::getId); + } + + /** + * 获得结算账户分页 + * + * @param pageReqVO 分页查询 + * @return 结算账户分页 + */ + PageResult getAccountPage(ErpAccountPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java new file mode 100644 index 000000000..578698b54 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java @@ -0,0 +1,113 @@ +package cn.iocoder.yudao.module.erp.service.finance; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +import cn.iocoder.yudao.module.erp.dal.mysql.finance.ErpAccountMapper; +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.erp.enums.ErrorCodeConstants.ACCOUNT_NOT_ENABLE; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.ACCOUNT_NOT_EXISTS; + +/** + * ERP 结算账户 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpAccountServiceImpl implements ErpAccountService { + + @Resource + private ErpAccountMapper accountMapper; + + @Override + public Long createAccount(ErpAccountSaveReqVO createReqVO) { + // 插入 + ErpAccountDO account = BeanUtils.toBean(createReqVO, ErpAccountDO.class); + accountMapper.insert(account); + // 返回 + return account.getId(); + } + + @Override + public void updateAccount(ErpAccountSaveReqVO updateReqVO) { + // 校验存在 + validateAccountExists(updateReqVO.getId()); + // 更新 + ErpAccountDO updateObj = BeanUtils.toBean(updateReqVO, ErpAccountDO.class); + accountMapper.updateById(updateObj); + } + + @Override + public void updateAccountDefaultStatus(Long id, Boolean defaultStatus) { + // 1. 校验存在 + validateAccountExists(id); + + // 2.1 如果开启,则需要关闭所有其它的默认 + if (defaultStatus) { + ErpAccountDO account = accountMapper.selectByDefaultStatus(); + if (account != null) { + accountMapper.updateById(new ErpAccountDO().setId(account.getId()).setDefaultStatus(false)); + } + } + // 2.2 更新对应的默认状态 + accountMapper.updateById(new ErpAccountDO().setId(id).setDefaultStatus(defaultStatus)); + } + + @Override + public void deleteAccount(Long id) { + // 校验存在 + validateAccountExists(id); + // 删除 + accountMapper.deleteById(id); + } + + private void validateAccountExists(Long id) { + if (accountMapper.selectById(id) == null) { + throw exception(ACCOUNT_NOT_EXISTS); + } + } + + @Override + public ErpAccountDO getAccount(Long id) { + return accountMapper.selectById(id); + } + + @Override + public ErpAccountDO validateAccount(Long id) { + ErpAccountDO account = accountMapper.selectById(id); + if (account == null) { + throw exception(ACCOUNT_NOT_EXISTS); + } + if (CommonStatusEnum.isDisable(account.getStatus())) { + throw exception(ACCOUNT_NOT_ENABLE, account.getName()); + } + return account; + } + + @Override + public List getAccountListByStatus(Integer status) { + return accountMapper.selectListByStatus(status); + } + + @Override + public List getAccountList(Collection ids) { + return accountMapper.selectBatchIds(ids); + } + + @Override + public PageResult getAccountPage(ErpAccountPageReqVO pageReqVO) { + return accountMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentService.java new file mode 100644 index 000000000..d66cfbea3 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentService.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.service.finance; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentItemDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * ERP 付款单 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpFinancePaymentService { + + /** + * 创建付款单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createFinancePayment(@Valid ErpFinancePaymentSaveReqVO createReqVO); + + /** + * 更新付款单 + * + * @param updateReqVO 更新信息 + */ + void updateFinancePayment(@Valid ErpFinancePaymentSaveReqVO updateReqVO); + + /** + * 更新付款单的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updateFinancePaymentStatus(Long id, Integer status); + + /** + * 删除付款单 + * + * @param ids 编号数组 + */ + void deleteFinancePayment(List ids); + + /** + * 获得付款单 + * + * @param id 编号 + * @return 付款单 + */ + ErpFinancePaymentDO getFinancePayment(Long id); + + /** + * 获得付款单分页 + * + * @param pageReqVO 分页查询 + * @return 付款单分页 + */ + PageResult getFinancePaymentPage(ErpFinancePaymentPageReqVO pageReqVO); + + // ==================== 付款单项 ==================== + + /** + * 获得付款单项列表 + * + * @param paymentId 付款单编号 + * @return 付款单项列表 + */ + List getFinancePaymentItemListByPaymentId(Long paymentId); + + /** + * 获得付款单项 List + * + * @param paymentIds 付款单编号数组 + * @return 付款单项 List + */ + List getFinancePaymentItemListByPaymentIds(Collection paymentIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java new file mode 100644 index 000000000..c7ed6b77d --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java @@ -0,0 +1,273 @@ +package cn.iocoder.yudao.module.erp.service.finance; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnDO; +import cn.iocoder.yudao.module.erp.dal.mysql.finance.ErpFinancePaymentItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.finance.ErpFinancePaymentMapper; +import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.enums.common.ErpBizTypeEnum; +import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseInService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseReturnService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 付款单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpFinancePaymentServiceImpl implements ErpFinancePaymentService { + + @Resource + private ErpFinancePaymentMapper financePaymentMapper; + @Resource + private ErpFinancePaymentItemMapper financePaymentItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpSupplierService supplierService; + @Resource + private ErpAccountService accountService; + @Resource + private ErpPurchaseInService purchaseInService; + @Resource + private ErpPurchaseReturnService purchaseReturnService; + + @Resource + private AdminUserApi adminUserApi; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createFinancePayment(ErpFinancePaymentSaveReqVO createReqVO) { + // 1.1 校验订单项的有效性 + List paymentItems = validateFinancePaymentItems( + createReqVO.getSupplierId(), createReqVO.getItems()); + // 1.2 校验供应商 + supplierService.validateSupplier(createReqVO.getSupplierId()); + // 1.3 校验结算账户 + if (createReqVO.getAccountId() != null) { + accountService.validateAccount(createReqVO.getAccountId()); + } + // 1.4 校验财务人员 + if (createReqVO.getFinanceUserId() != null) { + adminUserApi.validateUser(createReqVO.getFinanceUserId()); + } + // 1.5 生成付款单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.FINANCE_PAYMENT_NO_PREFIX); + if (financePaymentMapper.selectByNo(no) != null) { + throw exception(FINANCE_PAYMENT_NO_EXISTS); + } + + // 2.1 插入付款单 + ErpFinancePaymentDO payment = BeanUtils.toBean(createReqVO, ErpFinancePaymentDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus())); + calculateTotalPrice(payment, paymentItems); + financePaymentMapper.insert(payment); + // 2.2 插入付款单项 + paymentItems.forEach(o -> o.setPaymentId(payment.getId())); + financePaymentItemMapper.insertBatch(paymentItems); + + // 3. 更新采购入库、退货的付款金额情况 + updatePurchasePrice(paymentItems); + return payment.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateFinancePayment(ErpFinancePaymentSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpFinancePaymentDO payment = validateFinancePaymentExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(payment.getStatus())) { + throw exception(FINANCE_PAYMENT_UPDATE_FAIL_APPROVE, payment.getNo()); + } + // 1.2 校验供应商 + supplierService.validateSupplier(updateReqVO.getSupplierId()); + // 1.3 校验结算账户 + if (updateReqVO.getAccountId() != null) { + accountService.validateAccount(updateReqVO.getAccountId()); + } + // 1.4 校验财务人员 + if (updateReqVO.getFinanceUserId() != null) { + adminUserApi.validateUser(updateReqVO.getFinanceUserId()); + } + // 1.5 校验付款单项的有效性 + List paymentItems = validateFinancePaymentItems( + updateReqVO.getSupplierId(), updateReqVO.getItems()); + + // 2.1 更新付款单 + ErpFinancePaymentDO updateObj = BeanUtils.toBean(updateReqVO, ErpFinancePaymentDO.class); + calculateTotalPrice(updateObj, paymentItems); + financePaymentMapper.updateById(updateObj); + // 2.2 更新付款单项 + updateFinancePaymentItemList(updateReqVO.getId(), paymentItems); + } + + private void calculateTotalPrice(ErpFinancePaymentDO payment, List paymentItems) { + payment.setTotalPrice(getSumValue(paymentItems, ErpFinancePaymentItemDO::getPaymentPrice, BigDecimal::add, BigDecimal.ZERO)); + payment.setPaymentPrice(payment.getTotalPrice().subtract(payment.getDiscountPrice())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateFinancePaymentStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpFinancePaymentDO payment = validateFinancePaymentExists(id); + // 1.2 校验状态 + if (payment.getStatus().equals(status)) { + throw exception(approve ? FINANCE_PAYMENT_APPROVE_FAIL : FINANCE_PAYMENT_PROCESS_FAIL); + } + + // 2. 更新状态 + int updateCount = financePaymentMapper.updateByIdAndStatus(id, payment.getStatus(), + new ErpFinancePaymentDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? FINANCE_PAYMENT_APPROVE_FAIL : FINANCE_PAYMENT_PROCESS_FAIL); + } + } + + private List validateFinancePaymentItems( + Long supplierId, + List list) { + return convertList(list, o -> BeanUtils.toBean(o, ErpFinancePaymentItemDO.class, item -> { + if (ObjectUtil.equal(item.getBizType(), ErpBizTypeEnum.PURCHASE_IN.getType())) { + ErpPurchaseInDO purchaseIn = purchaseInService.validatePurchaseIn(item.getBizId()); + Assert.equals(purchaseIn.getSupplierId(), supplierId, "供应商必须相同"); + item.setTotalPrice(purchaseIn.getTotalPrice()).setBizNo(purchaseIn.getNo()); + } else if (ObjectUtil.equal(item.getBizType(), ErpBizTypeEnum.PURCHASE_RETURN.getType())) { + ErpPurchaseReturnDO purchaseReturn = purchaseReturnService.validatePurchaseReturn(item.getBizId()); + Assert.equals(purchaseReturn.getSupplierId(), supplierId, "供应商必须相同"); + item.setTotalPrice(purchaseReturn.getTotalPrice().negate()).setBizNo(purchaseReturn.getNo()); + } else { + throw new IllegalArgumentException("业务类型不正确:" + item.getBizType()); + } + })); + } + + private void updateFinancePaymentItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = financePaymentItemMapper.selectListByPaymentId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setPaymentId(id)); + financePaymentItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + financePaymentItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + financePaymentItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpFinancePaymentItemDO::getId)); + } + + // 第三步,更新采购入库、退货的付款金额情况 + updatePurchasePrice(CollectionUtils.newArrayList(diffList)); + } + + private void updatePurchasePrice(List paymentItems) { + paymentItems.forEach(paymentItem -> { + BigDecimal totalPaymentPrice = financePaymentItemMapper.selectPaymentPriceSumByBizIdAndBizType( + paymentItem.getBizId(), paymentItem.getBizType()); + if (ErpBizTypeEnum.PURCHASE_IN.getType().equals(paymentItem.getBizType())) { + purchaseInService.updatePurchaseInPaymentPrice(paymentItem.getBizId(), totalPaymentPrice); + } else if (ErpBizTypeEnum.PURCHASE_RETURN.getType().equals(paymentItem.getBizType())) { + purchaseReturnService.updatePurchaseReturnRefundPrice(paymentItem.getBizId(), totalPaymentPrice.negate()); + } else { + throw new IllegalArgumentException("业务类型不正确:" + paymentItem.getBizType()); + } + }); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteFinancePayment(List ids) { + // 1. 校验不处于已审批 + List payments = financePaymentMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(payments)) { + return; + } + payments.forEach(payment -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(payment.getStatus())) { + throw exception(FINANCE_PAYMENT_DELETE_FAIL_APPROVE, payment.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + payments.forEach(payment -> { + // 2.1 删除付款单 + financePaymentMapper.deleteById(payment.getId()); + // 2.2 删除付款单项 + List paymentItems = financePaymentItemMapper.selectListByPaymentId(payment.getId()); + financePaymentItemMapper.deleteBatchIds(convertSet(paymentItems, ErpFinancePaymentItemDO::getId)); + + // 2.3 更新采购入库、退货的付款金额情况 + updatePurchasePrice(paymentItems); + }); + } + + private ErpFinancePaymentDO validateFinancePaymentExists(Long id) { + ErpFinancePaymentDO payment = financePaymentMapper.selectById(id); + if (payment == null) { + throw exception(FINANCE_PAYMENT_NOT_EXISTS); + } + return payment; + } + + @Override + public ErpFinancePaymentDO getFinancePayment(Long id) { + return financePaymentMapper.selectById(id); + } + + @Override + public PageResult getFinancePaymentPage(ErpFinancePaymentPageReqVO pageReqVO) { + return financePaymentMapper.selectPage(pageReqVO); + } + + // ==================== 付款单项 ==================== + + @Override + public List getFinancePaymentItemListByPaymentId(Long paymentId) { + return financePaymentItemMapper.selectListByPaymentId(paymentId); + } + + @Override + public List getFinancePaymentItemListByPaymentIds(Collection paymentIds) { + if (CollUtil.isEmpty(paymentIds)) { + return Collections.emptyList(); + } + return financePaymentItemMapper.selectListByPaymentIds(paymentIds); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptService.java new file mode 100644 index 000000000..8e24d5d34 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptService.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.service.finance; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt.ErpFinanceReceiptPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt.ErpFinanceReceiptSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptItemDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * ERP 收款单 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpFinanceReceiptService { + + /** + * 创建收款单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createFinanceReceipt(@Valid ErpFinanceReceiptSaveReqVO createReqVO); + + /** + * 更新收款单 + * + * @param updateReqVO 更新信息 + */ + void updateFinanceReceipt(@Valid ErpFinanceReceiptSaveReqVO updateReqVO); + + /** + * 更新收款单的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updateFinanceReceiptStatus(Long id, Integer status); + + /** + * 删除收款单 + * + * @param ids 编号数组 + */ + void deleteFinanceReceipt(List ids); + + /** + * 获得收款单 + * + * @param id 编号 + * @return 收款单 + */ + ErpFinanceReceiptDO getFinanceReceipt(Long id); + + /** + * 获得收款单分页 + * + * @param pageReqVO 分页查询 + * @return 收款单分页 + */ + PageResult getFinanceReceiptPage(ErpFinanceReceiptPageReqVO pageReqVO); + + // ==================== 收款单项 ==================== + + /** + * 获得收款单项列表 + * + * @param receiptId 收款单编号 + * @return 收款单项列表 + */ + List getFinanceReceiptItemListByReceiptId(Long receiptId); + + /** + * 获得收款单项 List + * + * @param receiptIds 收款单编号数组 + * @return 收款单项 List + */ + List getFinanceReceiptItemListByReceiptIds(Collection receiptIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptServiceImpl.java new file mode 100644 index 000000000..031043a43 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptServiceImpl.java @@ -0,0 +1,273 @@ +package cn.iocoder.yudao.module.erp.service.finance; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt.ErpFinanceReceiptPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt.ErpFinanceReceiptSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnDO; +import cn.iocoder.yudao.module.erp.dal.mysql.finance.ErpFinanceReceiptItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.finance.ErpFinanceReceiptMapper; +import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.enums.common.ErpBizTypeEnum; +import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; +import cn.iocoder.yudao.module.erp.service.sale.ErpSaleOutService; +import cn.iocoder.yudao.module.erp.service.sale.ErpSaleReturnService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 收款单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpFinanceReceiptServiceImpl implements ErpFinanceReceiptService { + + @Resource + private ErpFinanceReceiptMapper financeReceiptMapper; + @Resource + private ErpFinanceReceiptItemMapper financeReceiptItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpCustomerService customerService; + @Resource + private ErpAccountService accountService; + @Resource + private ErpSaleOutService saleOutService; + @Resource + private ErpSaleReturnService saleReturnService; + + @Resource + private AdminUserApi adminUserApi; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createFinanceReceipt(ErpFinanceReceiptSaveReqVO createReqVO) { + // 1.1 校验订单项的有效性 + List receiptItems = validateFinanceReceiptItems( + createReqVO.getCustomerId(), createReqVO.getItems()); + // 1.2 校验客户 + customerService.validateCustomer(createReqVO.getCustomerId()); + // 1.3 校验结算账户 + if (createReqVO.getAccountId() != null) { + accountService.validateAccount(createReqVO.getAccountId()); + } + // 1.4 校验财务人员 + if (createReqVO.getFinanceUserId() != null) { + adminUserApi.validateUser(createReqVO.getFinanceUserId()); + } + // 1.5 生成收款单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.FINANCE_RECEIPT_NO_PREFIX); + if (financeReceiptMapper.selectByNo(no) != null) { + throw exception(FINANCE_RECEIPT_NO_EXISTS); + } + + // 2.1 插入收款单 + ErpFinanceReceiptDO receipt = BeanUtils.toBean(createReqVO, ErpFinanceReceiptDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus())); + calculateTotalPrice(receipt, receiptItems); + financeReceiptMapper.insert(receipt); + // 2.2 插入收款单项 + receiptItems.forEach(o -> o.setReceiptId(receipt.getId())); + financeReceiptItemMapper.insertBatch(receiptItems); + + // 3. 更新销售出库、退货的收款金额情况 + updateSalePrice(receiptItems); + return receipt.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateFinanceReceipt(ErpFinanceReceiptSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpFinanceReceiptDO receipt = validateFinanceReceiptExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(receipt.getStatus())) { + throw exception(FINANCE_RECEIPT_UPDATE_FAIL_APPROVE, receipt.getNo()); + } + // 1.2 校验客户 + customerService.validateCustomer(updateReqVO.getCustomerId()); + // 1.3 校验结算账户 + if (updateReqVO.getAccountId() != null) { + accountService.validateAccount(updateReqVO.getAccountId()); + } + // 1.4 校验财务人员 + if (updateReqVO.getFinanceUserId() != null) { + adminUserApi.validateUser(updateReqVO.getFinanceUserId()); + } + // 1.5 校验收款单项的有效性 + List receiptItems = validateFinanceReceiptItems( + updateReqVO.getCustomerId(), updateReqVO.getItems()); + + // 2.1 更新收款单 + ErpFinanceReceiptDO updateObj = BeanUtils.toBean(updateReqVO, ErpFinanceReceiptDO.class); + calculateTotalPrice(updateObj, receiptItems); + financeReceiptMapper.updateById(updateObj); + // 2.2 更新收款单项 + updateFinanceReceiptItemList(updateReqVO.getId(), receiptItems); + } + + private void calculateTotalPrice(ErpFinanceReceiptDO receipt, List receiptItems) { + receipt.setTotalPrice(getSumValue(receiptItems, ErpFinanceReceiptItemDO::getReceiptPrice, BigDecimal::add, BigDecimal.ZERO)); + receipt.setReceiptPrice(receipt.getTotalPrice().subtract(receipt.getDiscountPrice())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateFinanceReceiptStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpFinanceReceiptDO receipt = validateFinanceReceiptExists(id); + // 1.2 校验状态 + if (receipt.getStatus().equals(status)) { + throw exception(approve ? FINANCE_RECEIPT_APPROVE_FAIL : FINANCE_RECEIPT_PROCESS_FAIL); + } + + // 2. 更新状态 + int updateCount = financeReceiptMapper.updateByIdAndStatus(id, receipt.getStatus(), + new ErpFinanceReceiptDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? FINANCE_RECEIPT_APPROVE_FAIL : FINANCE_RECEIPT_PROCESS_FAIL); + } + } + + private List validateFinanceReceiptItems( + Long customerId, + List list) { + return convertList(list, o -> BeanUtils.toBean(o, ErpFinanceReceiptItemDO.class, item -> { + if (ObjectUtil.equal(item.getBizType(), ErpBizTypeEnum.SALE_OUT.getType())) { + ErpSaleOutDO saleOut = saleOutService.validateSaleOut(item.getBizId()); + Assert.equals(saleOut.getCustomerId(), customerId, "客户必须相同"); + item.setTotalPrice(saleOut.getTotalPrice()).setBizNo(saleOut.getNo()); + } else if (ObjectUtil.equal(item.getBizType(), ErpBizTypeEnum.SALE_RETURN.getType())) { + ErpSaleReturnDO saleReturn = saleReturnService.validateSaleReturn(item.getBizId()); + Assert.equals(saleReturn.getCustomerId(), customerId, "客户必须相同"); + item.setTotalPrice(saleReturn.getTotalPrice().negate()).setBizNo(saleReturn.getNo()); + } else { + throw new IllegalArgumentException("业务类型不正确:" + item.getBizType()); + } + })); + } + + private void updateFinanceReceiptItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = financeReceiptItemMapper.selectListByReceiptId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setReceiptId(id)); + financeReceiptItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + financeReceiptItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + financeReceiptItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpFinanceReceiptItemDO::getId)); + } + + // 第三步,更新销售出库、退货的收款金额情况 + updateSalePrice(CollectionUtils.newArrayList(diffList)); + } + + private void updateSalePrice(List receiptItems) { + receiptItems.forEach(receiptItem -> { + BigDecimal totalReceiptPrice = financeReceiptItemMapper.selectReceiptPriceSumByBizIdAndBizType( + receiptItem.getBizId(), receiptItem.getBizType()); + if (ErpBizTypeEnum.SALE_OUT.getType().equals(receiptItem.getBizType())) { + saleOutService.updateSaleInReceiptPrice(receiptItem.getBizId(), totalReceiptPrice); + } else if (ErpBizTypeEnum.SALE_RETURN.getType().equals(receiptItem.getBizType())) { + saleReturnService.updateSaleReturnRefundPrice(receiptItem.getBizId(), totalReceiptPrice.negate()); + } else { + throw new IllegalArgumentException("业务类型不正确:" + receiptItem.getBizType()); + } + }); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteFinanceReceipt(List ids) { + // 1. 校验不处于已审批 + List receipts = financeReceiptMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(receipts)) { + return; + } + receipts.forEach(receipt -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(receipt.getStatus())) { + throw exception(FINANCE_RECEIPT_DELETE_FAIL_APPROVE, receipt.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + receipts.forEach(receipt -> { + // 2.1 删除收款单 + financeReceiptMapper.deleteById(receipt.getId()); + // 2.2 删除收款单项 + List receiptItems = financeReceiptItemMapper.selectListByReceiptId(receipt.getId()); + financeReceiptItemMapper.deleteBatchIds(convertSet(receiptItems, ErpFinanceReceiptItemDO::getId)); + + // 2.3 更新销售出库、退货的收款金额情况 + updateSalePrice(receiptItems); + }); + } + + private ErpFinanceReceiptDO validateFinanceReceiptExists(Long id) { + ErpFinanceReceiptDO receipt = financeReceiptMapper.selectById(id); + if (receipt == null) { + throw exception(FINANCE_RECEIPT_NOT_EXISTS); + } + return receipt; + } + + @Override + public ErpFinanceReceiptDO getFinanceReceipt(Long id) { + return financeReceiptMapper.selectById(id); + } + + @Override + public PageResult getFinanceReceiptPage(ErpFinanceReceiptPageReqVO pageReqVO) { + return financeReceiptMapper.selectPage(pageReqVO); + } + + // ==================== 收款单项 ==================== + + @Override + public List getFinanceReceiptItemListByReceiptId(Long receiptId) { + return financeReceiptItemMapper.selectListByReceiptId(receiptId); + } + + @Override + public List getFinanceReceiptItemListByReceiptIds(Collection receiptIds) { + if (CollUtil.isEmpty(receiptIds)) { + return Collections.emptyList(); + } + return financeReceiptItemMapper.selectListByReceiptIds(receiptIds); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryService.java new file mode 100644 index 000000000..609bc4161 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryService.java @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.module.erp.service.product; + +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryListReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategorySaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * ERP 产品分类 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpProductCategoryService { + + /** + * 创建产品分类 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProductCategory(@Valid ErpProductCategorySaveReqVO createReqVO); + + /** + * 更新产品分类 + * + * @param updateReqVO 更新信息 + */ + void updateProductCategory(@Valid ErpProductCategorySaveReqVO updateReqVO); + + /** + * 删除产品分类 + * + * @param id 编号 + */ + void deleteProductCategory(Long id); + + /** + * 获得产品分类 + * + * @param id 编号 + * @return 产品分类 + */ + ErpProductCategoryDO getProductCategory(Long id); + + /** + * 获得产品分类列表 + * + * @param listReqVO 查询条件 + * @return 产品分类列表 + */ + List getProductCategoryList(ErpProductCategoryListReqVO listReqVO); + + /** + * 获得产品分类列表 + * + * @param ids 编号数组 + * @return 产品分类列表 + */ + List getProductCategoryList(Collection ids); + + /** + * 获得产品分类 Map + * + * @param ids 编号数组 + * @return 产品分类 Map + */ + default Map getProductCategoryMap(Collection ids) { + return convertMap(getProductCategoryList(ids), ErpProductCategoryDO::getId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java new file mode 100644 index 000000000..70062c0bb --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java @@ -0,0 +1,149 @@ +package cn.iocoder.yudao.module.erp.service.product; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryListReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategorySaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO; +import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductCategoryMapper; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +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.erp.enums.ErrorCodeConstants.*; + +/** + * ERP 产品分类 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpProductCategoryServiceImpl implements ErpProductCategoryService { + + @Resource + private ErpProductCategoryMapper erpProductCategoryMapper; + + @Resource + @Lazy // 延迟加载,避免循环依赖 + private ErpProductService productService; + + @Override + public Long createProductCategory(ErpProductCategorySaveReqVO createReqVO) { + // 校验父分类编号的有效性 + validateParentProductCategory(null, createReqVO.getParentId()); + // 校验分类名称的唯一性 + validateProductCategoryNameUnique(null, createReqVO.getParentId(), createReqVO.getName()); + + // 插入 + ErpProductCategoryDO category = BeanUtils.toBean(createReqVO, ErpProductCategoryDO.class); + erpProductCategoryMapper.insert(category); + // 返回 + return category.getId(); + } + + @Override + public void updateProductCategory(ErpProductCategorySaveReqVO updateReqVO) { + // 校验存在 + validateProductCategoryExists(updateReqVO.getId()); + // 校验父分类编号的有效性 + validateParentProductCategory(updateReqVO.getId(), updateReqVO.getParentId()); + // 校验分类名称的唯一性 + validateProductCategoryNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName()); + + // 更新 + ErpProductCategoryDO updateObj = BeanUtils.toBean(updateReqVO, ErpProductCategoryDO.class); + erpProductCategoryMapper.updateById(updateObj); + } + + @Override + public void deleteProductCategory(Long id) { + // 1.1 校验存在 + validateProductCategoryExists(id); + // 1.2 校验是否有子产品分类 + if (erpProductCategoryMapper.selectCountByParentId(id) > 0) { + throw exception(PRODUCT_CATEGORY_EXITS_CHILDREN); + } + // 1.3 校验是否有产品 + if (productService.getProductCountByCategoryId(id) > 0) { + throw exception(PRODUCT_CATEGORY_EXITS_PRODUCT); + } + // 2. 删除 + erpProductCategoryMapper.deleteById(id); + } + + private void validateProductCategoryExists(Long id) { + if (erpProductCategoryMapper.selectById(id) == null) { + throw exception(PRODUCT_CATEGORY_NOT_EXISTS); + } + } + + private void validateParentProductCategory(Long id, Long parentId) { + if (parentId == null || ErpProductCategoryDO.PARENT_ID_ROOT.equals(parentId)) { + return; + } + // 1. 不能设置自己为父产品分类 + if (Objects.equals(id, parentId)) { + throw exception(PRODUCT_CATEGORY_PARENT_ERROR); + } + // 2. 父产品分类不存在 + ErpProductCategoryDO parentCategory = erpProductCategoryMapper.selectById(parentId); + if (parentCategory == null) { + throw exception(PRODUCT_CATEGORY_PARENT_NOT_EXITS); + } + // 3. 递归校验父产品分类,如果父产品分类是自己的子产品分类,则报错,避免形成环路 + if (id == null) { // id 为空,说明新增,不需要考虑环路 + return; + } + for (int i = 0; i < Short.MAX_VALUE; i++) { + // 3.1 校验环路 + parentId = parentCategory.getParentId(); + if (Objects.equals(id, parentId)) { + throw exception(PRODUCT_CATEGORY_PARENT_IS_CHILD); + } + // 3.2 继续递归下一级父产品分类 + if (parentId == null || ErpProductCategoryDO.PARENT_ID_ROOT.equals(parentId)) { + break; + } + parentCategory = erpProductCategoryMapper.selectById(parentId); + if (parentCategory == null) { + break; + } + } + } + + private void validateProductCategoryNameUnique(Long id, Long parentId, String name) { + ErpProductCategoryDO productCategory = erpProductCategoryMapper.selectByParentIdAndName(parentId, name); + if (productCategory == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同 id 的产品分类 + if (id == null) { + throw exception(PRODUCT_CATEGORY_NAME_DUPLICATE); + } + if (!Objects.equals(productCategory.getId(), id)) { + throw exception(PRODUCT_CATEGORY_NAME_DUPLICATE); + } + } + + @Override + public ErpProductCategoryDO getProductCategory(Long id) { + return erpProductCategoryMapper.selectById(id); + } + + @Override + public List getProductCategoryList(ErpProductCategoryListReqVO listReqVO) { + return erpProductCategoryMapper.selectList(listReqVO); + } + + @Override + public List getProductCategoryList(Collection ids) { + return erpProductCategoryMapper.selectBatchIds(ids); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java new file mode 100644 index 000000000..a947e3b9d --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java @@ -0,0 +1,111 @@ +package cn.iocoder.yudao.module.erp.service.product; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * ERP 产品 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpProductService { + + /** + * 创建产品 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProduct(@Valid ProductSaveReqVO createReqVO); + + /** + * 更新产品 + * + * @param updateReqVO 更新信息 + */ + void updateProduct(@Valid ProductSaveReqVO updateReqVO); + + /** + * 删除产品 + * + * @param id 编号 + */ + void deleteProduct(Long id); + + /** + * 校验产品们的有效性 + * + * @param ids 编号数组 + * @return 产品列表 + */ + List validProductList(Collection ids); + + /** + * 获得产品 + * + * @param id 编号 + * @return 产品 + */ + ErpProductDO getProduct(Long id); + + /** + * 获得指定状态的产品 VO 列表 + * + * @param status 状态 + * @return 产品 VO 列表 + */ + List getProductVOListByStatus(Integer status); + + /** + * 获得产品 VO 列表 + * + * @param ids 编号数组 + * @return 产品 VO 列表 + */ + List getProductVOList(Collection ids); + + /** + * 获得产品 VO Map + * + * @param ids 编号数组 + * @return 产品 VO Map + */ + default Map getProductVOMap(Collection ids) { + return convertMap(getProductVOList(ids), ErpProductRespVO::getId); + } + + /** + * 获得产品 VO 分页 + * + * @param pageReqVO 分页查询 + * @return 产品分页 + */ + PageResult getProductVOPage(ErpProductPageReqVO pageReqVO); + + /** + * 基于产品分类编号,获得产品数量 + * + * @param categoryId 产品分类编号 + * @return 产品数量 + */ + Long getProductCountByCategoryId(Long categoryId); + + /** + * 基于产品单位编号,获得产品数量 + * + * @param unitId 产品单位编号 + * @return 产品数量 + */ + Long getProductCountByUnitId(Long unitId); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java new file mode 100644 index 000000000..c264b8e74 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java @@ -0,0 +1,152 @@ +package cn.iocoder.yudao.module.erp.service.product; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; +import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.PRODUCT_NOT_ENABLE; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.PRODUCT_NOT_EXISTS; + +/** + * ERP 产品 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpProductServiceImpl implements ErpProductService { + + @Resource + private ErpProductMapper productMapper; + + @Resource + private ErpProductCategoryService productCategoryService; + @Resource + private ErpProductUnitService productUnitService; + + @Override + public Long createProduct(ProductSaveReqVO createReqVO) { + // TODO 芋艿:校验分类 + // 插入 + ErpProductDO product = BeanUtils.toBean(createReqVO, ErpProductDO.class); + productMapper.insert(product); + // 返回 + return product.getId(); + } + + @Override + public void updateProduct(ProductSaveReqVO updateReqVO) { + // TODO 芋艿:校验分类 + // 校验存在 + validateProductExists(updateReqVO.getId()); + // 更新 + ErpProductDO updateObj = BeanUtils.toBean(updateReqVO, ErpProductDO.class); + productMapper.updateById(updateObj); + } + + @Override + public void deleteProduct(Long id) { + // 校验存在 + validateProductExists(id); + // 删除 + productMapper.deleteById(id); + } + + @Override + public List validProductList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + List list = productMapper.selectBatchIds(ids); + Map productMap = convertMap(list, ErpProductDO::getId); + for (Long id : ids) { + ErpProductDO product = productMap.get(id); + if (productMap.get(id) == null) { + throw exception(PRODUCT_NOT_EXISTS); + } + if (CommonStatusEnum.isDisable(product.getStatus())) { + throw exception(PRODUCT_NOT_ENABLE, product.getName()); + } + } + return list; + } + + private void validateProductExists(Long id) { + if (productMapper.selectById(id) == null) { + throw exception(PRODUCT_NOT_EXISTS); + } + } + + @Override + public ErpProductDO getProduct(Long id) { + return productMapper.selectById(id); + } + + @Override + public List getProductVOListByStatus(Integer status) { + List list = productMapper.selectListByStatus(status); + return buildProductVOList(list); + } + + @Override + public List getProductVOList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + List list = productMapper.selectBatchIds(ids); + return buildProductVOList(list); + } + + @Override + public PageResult getProductVOPage(ErpProductPageReqVO pageReqVO) { + PageResult pageResult = productMapper.selectPage(pageReqVO); + return new PageResult<>(buildProductVOList(pageResult.getList()), pageResult.getTotal()); + } + + private List buildProductVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + Map categoryMap = productCategoryService.getProductCategoryMap( + convertSet(list, ErpProductDO::getCategoryId)); + Map unitMap = productUnitService.getProductUnitMap( + convertSet(list, ErpProductDO::getUnitId)); + return BeanUtils.toBean(list, ErpProductRespVO.class, product -> { + MapUtils.findAndThen(categoryMap, product.getCategoryId(), + category -> product.setCategoryName(category.getName())); + MapUtils.findAndThen(unitMap, product.getUnitId(), + unit -> product.setUnitName(unit.getName())); + }); + } + + @Override + public Long getProductCountByCategoryId(Long categoryId) { + return productMapper.selectCountByCategoryId(categoryId); + } + + @Override + public Long getProductCountByUnitId(Long unitId) { + return productMapper.selectCountByUnitId(unitId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitService.java new file mode 100644 index 000000000..93776adac --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitService.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.erp.service.product; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * ERP 产品单位 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpProductUnitService { + + /** + * 创建产品单位 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProductUnit(@Valid ErpProductUnitSaveReqVO createReqVO); + + /** + * 更新产品单位 + * + * @param updateReqVO 更新信息 + */ + void updateProductUnit(@Valid ErpProductUnitSaveReqVO updateReqVO); + + /** + * 删除产品单位 + * + * @param id 编号 + */ + void deleteProductUnit(Long id); + + /** + * 获得产品单位 + * + * @param id 编号 + * @return 产品单位 + */ + ErpProductUnitDO getProductUnit(Long id); + + /** + * 获得产品单位分页 + * + * @param pageReqVO 分页查询 + * @return 产品单位分页 + */ + PageResult getProductUnitPage(ErpProductUnitPageReqVO pageReqVO); + + /** + * 获得指定状态的产品单位列表 + * + * @param status 状态 + * @return 产品单位列表 + */ + List getProductUnitListByStatus(Integer status); + + /** + * 获得产品单位列表 + * + * @param ids 编号数组 + * @return 产品单位列表 + */ + List getProductUnitList(Collection ids); + + /** + * 获得产品单位 Map + * + * @param ids 编号数组 + * @return 产品单位 Map + */ + default Map getProductUnitMap(Collection ids) { + return convertMap(getProductUnitList(ids), ErpProductUnitDO::getId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java new file mode 100644 index 000000000..d2592a492 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java @@ -0,0 +1,111 @@ +package cn.iocoder.yudao.module.erp.service.product; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; +import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductUnitMapper; +import com.google.common.annotations.VisibleForTesting; +import org.springframework.context.annotation.Lazy; +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.erp.enums.ErrorCodeConstants.*; + +/** + * ERP 产品单位 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpProductUnitServiceImpl implements ErpProductUnitService { + + @Resource + private ErpProductUnitMapper productUnitMapper; + + @Resource + @Lazy // 延迟加载,避免循环依赖 + private ErpProductService productService; + + @Override + public Long createProductUnit(ErpProductUnitSaveReqVO createReqVO) { + // 1. 校验名字唯一 + validateProductUnitNameUnique(null, createReqVO.getName()); + // 2. 插入 + ErpProductUnitDO unit = BeanUtils.toBean(createReqVO, ErpProductUnitDO.class); + productUnitMapper.insert(unit); + return unit.getId(); + } + + @Override + public void updateProductUnit(ErpProductUnitSaveReqVO updateReqVO) { + // 1.1 校验存在 + validateProductUnitExists(updateReqVO.getId()); + // 1.2 校验名字唯一 + validateProductUnitNameUnique(updateReqVO.getId(), updateReqVO.getName()); + // 2. 更新 + ErpProductUnitDO updateObj = BeanUtils.toBean(updateReqVO, ErpProductUnitDO.class); + productUnitMapper.updateById(updateObj); + } + + @VisibleForTesting + void validateProductUnitNameUnique(Long id, String name) { + ErpProductUnitDO unit = productUnitMapper.selectByName(name); + if (unit == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同 id 的字典类型 + if (id == null) { + throw exception(PRODUCT_UNIT_NAME_DUPLICATE); + } + if (!unit.getId().equals(id)) { + throw exception(PRODUCT_UNIT_NAME_DUPLICATE); + } + } + + @Override + public void deleteProductUnit(Long id) { + // 1.1 校验存在 + validateProductUnitExists(id); + // 1.2 校验产品是否使用 + if (productService.getProductCountByUnitId(id) > 0) { + throw exception(PRODUCT_UNIT_EXITS_PRODUCT); + } + // 2. 删除 + productUnitMapper.deleteById(id); + } + + private void validateProductUnitExists(Long id) { + if (productUnitMapper.selectById(id) == null) { + throw exception(PRODUCT_UNIT_NOT_EXISTS); + } + } + + @Override + public ErpProductUnitDO getProductUnit(Long id) { + return productUnitMapper.selectById(id); + } + + @Override + public PageResult getProductUnitPage(ErpProductUnitPageReqVO pageReqVO) { + return productUnitMapper.selectPage(pageReqVO); + } + + @Override + public List getProductUnitListByStatus(Integer status) { + return productUnitMapper.selectListByStatus(status); + } + + @Override + public List getProductUnitList(Collection ids) { + return productUnitMapper.selectBatchIds(ids); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java new file mode 100644 index 000000000..6c994e894 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java @@ -0,0 +1,101 @@ +package cn.iocoder.yudao.module.erp.service.purchase; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in.ErpPurchaseInPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in.ErpPurchaseInSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInItemDO; + +import javax.validation.Valid; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.List; + +/** + * ERP 采购入库 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpPurchaseInService { + + /** + * 创建采购入库 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createPurchaseIn(@Valid ErpPurchaseInSaveReqVO createReqVO); + + /** + * 更新采购入库 + * + * @param updateReqVO 更新信息 + */ + void updatePurchaseIn(@Valid ErpPurchaseInSaveReqVO updateReqVO); + + /** + * 更新采购入库的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updatePurchaseInStatus(Long id, Integer status); + + /** + * 更新采购入库的付款金额 + * + * @param id 编号 + * @param paymentPrice 付款金额 + */ + void updatePurchaseInPaymentPrice(Long id, BigDecimal paymentPrice); + + /** + * 删除采购入库 + * + * @param ids 编号数组 + */ + void deletePurchaseIn(List ids); + + /** + * 获得采购入库 + * + * @param id 编号 + * @return 采购入库 + */ + ErpPurchaseInDO getPurchaseIn(Long id); + + /** + * 校验采购入库,已经审核通过 + * + * @param id 编号 + * @return 采购入库 + */ + ErpPurchaseInDO validatePurchaseIn(Long id); + + /** + * 获得采购入库分页 + * + * @param pageReqVO 分页查询 + * @return 采购入库分页 + */ + PageResult getPurchaseInPage(ErpPurchaseInPageReqVO pageReqVO); + + // ==================== 采购入库项 ==================== + + /** + * 获得采购入库项列表 + * + * @param inId 采购入库编号 + * @return 采购入库项列表 + */ + List getPurchaseInItemListByInId(Long inId); + + /** + * 获得采购入库项 List + * + * @param inIds 采购入库编号数组 + * @return 采购入库项 List + */ + List getPurchaseInItemListByInIds(Collection inIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java new file mode 100644 index 000000000..acbdb24db --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java @@ -0,0 +1,308 @@ +package cn.iocoder.yudao.module.erp.service.purchase; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in.ErpPurchaseInPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in.ErpPurchaseInSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO; +import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseInItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseInMapper; +import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; +import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockRecordService; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 采购入库 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpPurchaseInServiceImpl implements ErpPurchaseInService { + + @Resource + private ErpPurchaseInMapper purchaseInMapper; + @Resource + private ErpPurchaseInItemMapper purchaseInItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpProductService productService; + @Resource + @Lazy // 延迟加载,避免循环依赖 + private ErpPurchaseOrderService purchaseOrderService; + @Resource + private ErpAccountService accountService; + @Resource + private ErpStockRecordService stockRecordService; + + @Resource + private AdminUserApi adminUserApi; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createPurchaseIn(ErpPurchaseInSaveReqVO createReqVO) { + // 1.1 校验采购订单已审核 + ErpPurchaseOrderDO purchaseOrder = purchaseOrderService.validatePurchaseOrder(createReqVO.getOrderId()); + // 1.2 校验入库项的有效性 + List purchaseInItems = validatePurchaseInItems(createReqVO.getItems()); + // 1.3 校验结算账户 + accountService.validateAccount(createReqVO.getAccountId()); + // 1.4 生成入库单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.PURCHASE_IN_NO_PREFIX); + if (purchaseInMapper.selectByNo(no) != null) { + throw exception(PURCHASE_IN_NO_EXISTS); + } + + // 2.1 插入入库 + ErpPurchaseInDO purchaseIn = BeanUtils.toBean(createReqVO, ErpPurchaseInDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus())) + .setOrderNo(purchaseOrder.getNo()).setSupplierId(purchaseOrder.getSupplierId()); + calculateTotalPrice(purchaseIn, purchaseInItems); + purchaseInMapper.insert(purchaseIn); + // 2.2 插入入库项 + purchaseInItems.forEach(o -> o.setInId(purchaseIn.getId())); + purchaseInItemMapper.insertBatch(purchaseInItems); + + // 3. 更新采购订单的入库数量 + updatePurchaseOrderInCount(createReqVO.getOrderId()); + return purchaseIn.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updatePurchaseIn(ErpPurchaseInSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpPurchaseInDO purchaseIn = validatePurchaseInExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(purchaseIn.getStatus())) { + throw exception(PURCHASE_IN_UPDATE_FAIL_APPROVE, purchaseIn.getNo()); + } + // 1.2 校验采购订单已审核 + ErpPurchaseOrderDO purchaseOrder = purchaseOrderService.validatePurchaseOrder(updateReqVO.getOrderId()); + // 1.3 校验结算账户 + accountService.validateAccount(updateReqVO.getAccountId()); + // 1.4 校验订单项的有效性 + List purchaseInItems = validatePurchaseInItems(updateReqVO.getItems()); + + // 2.1 更新入库 + ErpPurchaseInDO updateObj = BeanUtils.toBean(updateReqVO, ErpPurchaseInDO.class) + .setOrderNo(purchaseOrder.getNo()).setSupplierId(purchaseOrder.getSupplierId()); + calculateTotalPrice(updateObj, purchaseInItems); + purchaseInMapper.updateById(updateObj); + // 2.2 更新入库项 + updatePurchaseInItemList(updateReqVO.getId(), purchaseInItems); + + // 3.1 更新采购订单的入库数量 + updatePurchaseOrderInCount(updateObj.getOrderId()); + // 3.2 注意:如果采购订单编号变更了,需要更新“老”采购订单的入库数量 + if (ObjectUtil.notEqual(purchaseIn.getOrderId(), updateObj.getOrderId())) { + updatePurchaseOrderInCount(purchaseIn.getOrderId()); + } + } + + private void calculateTotalPrice(ErpPurchaseInDO purchaseIn, List purchaseInItems) { + purchaseIn.setTotalCount(getSumValue(purchaseInItems, ErpPurchaseInItemDO::getCount, BigDecimal::add)); + purchaseIn.setTotalProductPrice(getSumValue(purchaseInItems, ErpPurchaseInItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)); + purchaseIn.setTotalTaxPrice(getSumValue(purchaseInItems, ErpPurchaseInItemDO::getTaxPrice, BigDecimal::add, BigDecimal.ZERO)); + purchaseIn.setTotalPrice(purchaseIn.getTotalProductPrice().add(purchaseIn.getTotalTaxPrice())); + // 计算优惠价格 + if (purchaseIn.getDiscountPercent() == null) { + purchaseIn.setDiscountPercent(BigDecimal.ZERO); + } + purchaseIn.setDiscountPrice(MoneyUtils.priceMultiplyPercent(purchaseIn.getTotalPrice(), purchaseIn.getDiscountPercent())); + purchaseIn.setTotalPrice(purchaseIn.getTotalPrice().subtract(purchaseIn.getDiscountPrice().add(purchaseIn.getOtherPrice()))); + } + + private void updatePurchaseOrderInCount(Long orderId) { + // 1.1 查询采购订单对应的采购入库单列表 + List purchaseIns = purchaseInMapper.selectListByOrderId(orderId); + // 1.2 查询对应的采购订单项的入库数量 + Map returnCountMap = purchaseInItemMapper.selectOrderItemCountSumMapByInIds( + convertList(purchaseIns, ErpPurchaseInDO::getId)); + // 2. 更新采购订单的入库数量 + purchaseOrderService.updatePurchaseOrderInCount(orderId, returnCountMap); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updatePurchaseInStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpPurchaseInDO purchaseIn = validatePurchaseInExists(id); + // 1.2 校验状态 + if (purchaseIn.getStatus().equals(status)) { + throw exception(approve ? PURCHASE_IN_APPROVE_FAIL : PURCHASE_IN_PROCESS_FAIL); + } + // 1.3 校验已付款 + if (approve && purchaseIn.getPaymentPrice().compareTo(BigDecimal.ZERO) > 0) { + throw exception(PURCHASE_IN_PROCESS_FAIL_EXISTS_PAYMENT); + } + + // 2. 更新状态 + int updateCount = purchaseInMapper.updateByIdAndStatus(id, purchaseIn.getStatus(), + new ErpPurchaseInDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? PURCHASE_IN_APPROVE_FAIL : PURCHASE_IN_PROCESS_FAIL); + } + + // 3. 变更库存 + List purchaseInItems = purchaseInItemMapper.selectListByInId(id); + Integer bizType = approve ? ErpStockRecordBizTypeEnum.PURCHASE_IN.getType() + : ErpStockRecordBizTypeEnum.PURCHASE_IN_CANCEL.getType(); + purchaseInItems.forEach(purchaseInItem -> { + BigDecimal count = approve ? purchaseInItem.getCount() : purchaseInItem.getCount().negate(); + stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( + purchaseInItem.getProductId(), purchaseInItem.getWarehouseId(), count, + bizType, purchaseInItem.getInId(), purchaseInItem.getId(), purchaseIn.getNo())); + }); + } + + @Override + public void updatePurchaseInPaymentPrice(Long id, BigDecimal paymentPrice) { + ErpPurchaseInDO purchaseIn = purchaseInMapper.selectById(id); + if (purchaseIn.getPaymentPrice().equals(paymentPrice)) { + return; + } + if (paymentPrice.compareTo(purchaseIn.getTotalPrice()) > 0) { + throw exception(PURCHASE_IN_FAIL_PAYMENT_PRICE_EXCEED, paymentPrice, purchaseIn.getTotalPrice()); + } + purchaseInMapper.updateById(new ErpPurchaseInDO().setId(id).setPaymentPrice(paymentPrice)); + } + + private List validatePurchaseInItems(List list) { + // 1. 校验产品存在 + List productList = productService.validProductList( + convertSet(list, ErpPurchaseInSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + // 2. 转化为 ErpPurchaseInItemDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, ErpPurchaseInItemDO.class, item -> { + item.setProductUnitId(productMap.get(item.getProductId()).getUnitId()); + item.setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())); + if (item.getTotalPrice() == null) { + return; + } + if (item.getTaxPercent() != null) { + item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent())); + } + })); + } + + private void updatePurchaseInItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = purchaseInItemMapper.selectListByInId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setInId(id)); + purchaseInItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + purchaseInItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + purchaseInItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpPurchaseInItemDO::getId)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deletePurchaseIn(List ids) { + // 1. 校验不处于已审批 + List purchaseIns = purchaseInMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(purchaseIns)) { + return; + } + purchaseIns.forEach(purchaseIn -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(purchaseIn.getStatus())) { + throw exception(PURCHASE_IN_DELETE_FAIL_APPROVE, purchaseIn.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + purchaseIns.forEach(purchaseIn -> { + // 2.1 删除订单 + purchaseInMapper.deleteById(purchaseIn.getId()); + // 2.2 删除订单项 + purchaseInItemMapper.deleteByInId(purchaseIn.getId()); + + // 2.3 更新采购订单的入库数量 + updatePurchaseOrderInCount(purchaseIn.getOrderId()); + }); + + } + + private ErpPurchaseInDO validatePurchaseInExists(Long id) { + ErpPurchaseInDO purchaseIn = purchaseInMapper.selectById(id); + if (purchaseIn == null) { + throw exception(PURCHASE_IN_NOT_EXISTS); + } + return purchaseIn; + } + + @Override + public ErpPurchaseInDO getPurchaseIn(Long id) { + return purchaseInMapper.selectById(id); + } + + @Override + public ErpPurchaseInDO validatePurchaseIn(Long id) { + ErpPurchaseInDO purchaseIn = validatePurchaseInExists(id); + if (ObjectUtil.notEqual(purchaseIn.getStatus(), ErpAuditStatus.APPROVE.getStatus())) { + throw exception(PURCHASE_IN_NOT_APPROVE); + } + return purchaseIn; + } + + @Override + public PageResult getPurchaseInPage(ErpPurchaseInPageReqVO pageReqVO) { + return purchaseInMapper.selectPage(pageReqVO); + } + + // ==================== 采购入库项 ==================== + + @Override + public List getPurchaseInItemListByInId(Long inId) { + return purchaseInItemMapper.selectListByInId(inId); + } + + @Override + public List getPurchaseInItemListByInIds(Collection inIds) { + if (CollUtil.isEmpty(inIds)) { + return Collections.emptyList(); + } + return purchaseInItemMapper.selectListByInIds(inIds); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderService.java new file mode 100644 index 000000000..29d5f6f3f --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderService.java @@ -0,0 +1,110 @@ +package cn.iocoder.yudao.module.erp.service.purchase; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO; + +import javax.validation.Valid; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * ERP 采购订单 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpPurchaseOrderService { + + /** + * 创建采购订单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createPurchaseOrder(@Valid ErpPurchaseOrderSaveReqVO createReqVO); + + /** + * 更新采购订单 + * + * @param updateReqVO 更新信息 + */ + void updatePurchaseOrder(@Valid ErpPurchaseOrderSaveReqVO updateReqVO); + + /** + * 更新采购订单的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updatePurchaseOrderStatus(Long id, Integer status); + + /** + * 更新采购订单的入库数量 + * + * @param id 编号 + * @param inCountMap 入库数量 Map:key 采购订单项编号;value 入库数量 + */ + void updatePurchaseOrderInCount(Long id, Map inCountMap); + + /** + * 更新采购订单的退货数量 + * + * @param orderId 编号 + * @param returnCountMap 退货数量 Map:key 采购订单项编号;value 退货数量 + */ + void updatePurchaseOrderReturnCount(Long orderId, Map returnCountMap); + + /** + * 删除采购订单 + * + * @param ids 编号数组 + */ + void deletePurchaseOrder(List ids); + + /** + * 获得采购订单 + * + * @param id 编号 + * @return 采购订单 + */ + ErpPurchaseOrderDO getPurchaseOrder(Long id); + + /** + * 校验采购订单,已经审核通过 + * + * @param id 编号 + * @return 采购订单 + */ + ErpPurchaseOrderDO validatePurchaseOrder(Long id); + + /** + * 获得采购订单分页 + * + * @param pageReqVO 分页查询 + * @return 采购订单分页 + */ + PageResult getPurchaseOrderPage(ErpPurchaseOrderPageReqVO pageReqVO); + + // ==================== 采购订单项 ==================== + + /** + * 获得采购订单项列表 + * + * @param orderId 采购订单编号 + * @return 采购订单项列表 + */ + List getPurchaseOrderItemListByOrderId(Long orderId); + + /** + * 获得采购订单项 List + * + * @param orderIds 采购订单编号数组 + * @return 采购订单项 List + */ + List getPurchaseOrderItemListByOrderIds(Collection orderIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java new file mode 100644 index 000000000..c585490b9 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java @@ -0,0 +1,295 @@ +package cn.iocoder.yudao.module.erp.service.purchase; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseOrderItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseOrderMapper; +import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 采购订单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpPurchaseOrderServiceImpl implements ErpPurchaseOrderService { + + @Resource + private ErpPurchaseOrderMapper purchaseOrderMapper; + @Resource + private ErpPurchaseOrderItemMapper purchaseOrderItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpProductService productService; + @Resource + private ErpSupplierService supplierService; + @Resource + private ErpAccountService accountService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createPurchaseOrder(ErpPurchaseOrderSaveReqVO createReqVO) { + // 1.1 校验订单项的有效性 + List purchaseOrderItems = validatePurchaseOrderItems(createReqVO.getItems()); + // 1.2 校验供应商 + supplierService.validateSupplier(createReqVO.getSupplierId()); + // 1.3 校验结算账户 + if (createReqVO.getAccountId() != null) { + accountService.validateAccount(createReqVO.getAccountId()); + } + // 1.4 生成订单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.PURCHASE_ORDER_NO_PREFIX); + if (purchaseOrderMapper.selectByNo(no) != null) { + throw exception(PURCHASE_ORDER_NO_EXISTS); + } + + // 2.1 插入订单 + ErpPurchaseOrderDO purchaseOrder = BeanUtils.toBean(createReqVO, ErpPurchaseOrderDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus())); + calculateTotalPrice(purchaseOrder, purchaseOrderItems); + purchaseOrderMapper.insert(purchaseOrder); + // 2.2 插入订单项 + purchaseOrderItems.forEach(o -> o.setOrderId(purchaseOrder.getId())); + purchaseOrderItemMapper.insertBatch(purchaseOrderItems); + return purchaseOrder.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updatePurchaseOrder(ErpPurchaseOrderSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpPurchaseOrderDO purchaseOrder = validatePurchaseOrderExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(purchaseOrder.getStatus())) { + throw exception(PURCHASE_ORDER_UPDATE_FAIL_APPROVE, purchaseOrder.getNo()); + } + // 1.2 校验供应商 + supplierService.validateSupplier(updateReqVO.getSupplierId()); + // 1.3 校验结算账户 + if (updateReqVO.getAccountId() != null) { + accountService.validateAccount(updateReqVO.getAccountId()); + } + // 1.4 校验订单项的有效性 + List purchaseOrderItems = validatePurchaseOrderItems(updateReqVO.getItems()); + + // 2.1 更新订单 + ErpPurchaseOrderDO updateObj = BeanUtils.toBean(updateReqVO, ErpPurchaseOrderDO.class); + calculateTotalPrice(updateObj, purchaseOrderItems); + purchaseOrderMapper.updateById(updateObj); + // 2.2 更新订单项 + updatePurchaseOrderItemList(updateReqVO.getId(), purchaseOrderItems); + } + + private void calculateTotalPrice(ErpPurchaseOrderDO purchaseOrder, List purchaseOrderItems) { + purchaseOrder.setTotalCount(getSumValue(purchaseOrderItems, ErpPurchaseOrderItemDO::getCount, BigDecimal::add)); + purchaseOrder.setTotalProductPrice(getSumValue(purchaseOrderItems, ErpPurchaseOrderItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)); + purchaseOrder.setTotalTaxPrice(getSumValue(purchaseOrderItems, ErpPurchaseOrderItemDO::getTaxPrice, BigDecimal::add, BigDecimal.ZERO)); + purchaseOrder.setTotalPrice(purchaseOrder.getTotalProductPrice().add(purchaseOrder.getTotalTaxPrice())); + // 计算优惠价格 + if (purchaseOrder.getDiscountPercent() == null) { + purchaseOrder.setDiscountPercent(BigDecimal.ZERO); + } + purchaseOrder.setDiscountPrice(MoneyUtils.priceMultiplyPercent(purchaseOrder.getTotalPrice(), purchaseOrder.getDiscountPercent())); + purchaseOrder.setTotalPrice(purchaseOrder.getTotalPrice().subtract(purchaseOrder.getDiscountPrice())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updatePurchaseOrderStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpPurchaseOrderDO purchaseOrder = validatePurchaseOrderExists(id); + // 1.2 校验状态 + if (purchaseOrder.getStatus().equals(status)) { + throw exception(approve ? PURCHASE_ORDER_APPROVE_FAIL : PURCHASE_ORDER_PROCESS_FAIL); + } + // 1.3 存在采购入单,无法反审核 + if (!approve && purchaseOrder.getInCount().compareTo(BigDecimal.ZERO) > 0) { + throw exception(PURCHASE_ORDER_PROCESS_FAIL_EXISTS_IN); + } + // 1.4 存在采购退货单,无法反审核 + if (!approve && purchaseOrder.getReturnCount().compareTo(BigDecimal.ZERO) > 0) { + throw exception(PURCHASE_ORDER_PROCESS_FAIL_EXISTS_RETURN); + } + + // 2. 更新状态 + int updateCount = purchaseOrderMapper.updateByIdAndStatus(id, purchaseOrder.getStatus(), + new ErpPurchaseOrderDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? PURCHASE_ORDER_APPROVE_FAIL : PURCHASE_ORDER_PROCESS_FAIL); + } + } + + private List validatePurchaseOrderItems(List list) { + // 1. 校验产品存在 + List productList = productService.validProductList( + convertSet(list, ErpPurchaseOrderSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + // 2. 转化为 ErpPurchaseOrderItemDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, ErpPurchaseOrderItemDO.class, item -> { + item.setProductUnitId(productMap.get(item.getProductId()).getUnitId()); + item.setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())); + if (item.getTotalPrice() == null) { + return; + } + if (item.getTaxPercent() != null) { + item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent())); + } + })); + } + + private void updatePurchaseOrderItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = purchaseOrderItemMapper.selectListByOrderId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setOrderId(id)); + purchaseOrderItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + purchaseOrderItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + purchaseOrderItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpPurchaseOrderItemDO::getId)); + } + } + + @Override + public void updatePurchaseOrderInCount(Long id, Map inCountMap) { + List orderItems = purchaseOrderItemMapper.selectListByOrderId(id); + // 1. 更新每个采购订单项 + orderItems.forEach(item -> { + BigDecimal inCount = inCountMap.getOrDefault(item.getId(), BigDecimal.ZERO); + if (item.getInCount().equals(inCount)) { + return; + } + if (inCount.compareTo(item.getCount()) > 0) { + throw exception(PURCHASE_ORDER_ITEM_IN_FAIL_PRODUCT_EXCEED, + productService.getProduct(item.getProductId()).getName(), item.getCount()); + } + purchaseOrderItemMapper.updateById(new ErpPurchaseOrderItemDO().setId(item.getId()).setInCount(inCount)); + }); + // 2. 更新采购订单 + BigDecimal totalInCount = getSumValue(inCountMap.values(), value -> value, BigDecimal::add, BigDecimal.ZERO); + purchaseOrderMapper.updateById(new ErpPurchaseOrderDO().setId(id).setInCount(totalInCount)); + } + + @Override + public void updatePurchaseOrderReturnCount(Long orderId, Map returnCountMap) { + List orderItems = purchaseOrderItemMapper.selectListByOrderId(orderId); + // 1. 更新每个采购订单项 + orderItems.forEach(item -> { + BigDecimal returnCount = returnCountMap.getOrDefault(item.getId(), BigDecimal.ZERO); + if (item.getReturnCount().equals(returnCount)) { + return; + } + if (returnCount.compareTo(item.getInCount()) > 0) { + throw exception(PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED, + productService.getProduct(item.getProductId()).getName(), item.getInCount()); + } + purchaseOrderItemMapper.updateById(new ErpPurchaseOrderItemDO().setId(item.getId()).setReturnCount(returnCount)); + }); + // 2. 更新采购订单 + BigDecimal totalReturnCount = getSumValue(returnCountMap.values(), value -> value, BigDecimal::add, BigDecimal.ZERO); + purchaseOrderMapper.updateById(new ErpPurchaseOrderDO().setId(orderId).setReturnCount(totalReturnCount)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deletePurchaseOrder(List ids) { + // 1. 校验不处于已审批 + List purchaseOrders = purchaseOrderMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(purchaseOrders)) { + return; + } + purchaseOrders.forEach(purchaseOrder -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(purchaseOrder.getStatus())) { + throw exception(PURCHASE_ORDER_DELETE_FAIL_APPROVE, purchaseOrder.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + purchaseOrders.forEach(purchaseOrder -> { + // 2.1 删除订单 + purchaseOrderMapper.deleteById(purchaseOrder.getId()); + // 2.2 删除订单项 + purchaseOrderItemMapper.deleteByOrderId(purchaseOrder.getId()); + }); + } + + private ErpPurchaseOrderDO validatePurchaseOrderExists(Long id) { + ErpPurchaseOrderDO purchaseOrder = purchaseOrderMapper.selectById(id); + if (purchaseOrder == null) { + throw exception(PURCHASE_ORDER_NOT_EXISTS); + } + return purchaseOrder; + } + + @Override + public ErpPurchaseOrderDO getPurchaseOrder(Long id) { + return purchaseOrderMapper.selectById(id); + } + + @Override + public ErpPurchaseOrderDO validatePurchaseOrder(Long id) { + ErpPurchaseOrderDO purchaseOrder = validatePurchaseOrderExists(id); + if (ObjectUtil.notEqual(purchaseOrder.getStatus(), ErpAuditStatus.APPROVE.getStatus())) { + throw exception(PURCHASE_ORDER_NOT_APPROVE); + } + return purchaseOrder; + } + + @Override + public PageResult getPurchaseOrderPage(ErpPurchaseOrderPageReqVO pageReqVO) { + return purchaseOrderMapper.selectPage(pageReqVO); + } + + // ==================== 订单项 ==================== + + @Override + public List getPurchaseOrderItemListByOrderId(Long orderId) { + return purchaseOrderItemMapper.selectListByOrderId(orderId); + } + + @Override + public List getPurchaseOrderItemListByOrderIds(Collection orderIds) { + if (CollUtil.isEmpty(orderIds)) { + return Collections.emptyList(); + } + return purchaseOrderItemMapper.selectListByOrderIds(orderIds); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java new file mode 100644 index 000000000..9c4a4ab3b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java @@ -0,0 +1,101 @@ +package cn.iocoder.yudao.module.erp.service.purchase; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns.ErpPurchaseReturnPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns.ErpPurchaseReturnSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnItemDO; + +import javax.validation.Valid; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.List; + +/** + * ERP 采购退货 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpPurchaseReturnService { + + /** + * 创建采购退货 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createPurchaseReturn(@Valid ErpPurchaseReturnSaveReqVO createReqVO); + + /** + * 更新采购退货 + * + * @param updateReqVO 更新信息 + */ + void updatePurchaseReturn(@Valid ErpPurchaseReturnSaveReqVO updateReqVO); + + /** + * 更新采购退货的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updatePurchaseReturnStatus(Long id, Integer status); + + /** + * 更新采购退货的退款金额 + * + * @param id 编号 + * @param refundPrice 退款金额 + */ + void updatePurchaseReturnRefundPrice(Long id, BigDecimal refundPrice); + + /** + * 删除采购退货 + * + * @param ids 编号数组 + */ + void deletePurchaseReturn(List ids); + + /** + * 获得采购退货 + * + * @param id 编号 + * @return 采购退货 + */ + ErpPurchaseReturnDO getPurchaseReturn(Long id); + + /** + * 校验采购退货,已经审核通过 + * + * @param id 编号 + * @return 采购退货 + */ + ErpPurchaseReturnDO validatePurchaseReturn(Long id); + + /** + * 获得采购退货分页 + * + * @param pageReqVO 分页查询 + * @return 采购退货分页 + */ + PageResult getPurchaseReturnPage(ErpPurchaseReturnPageReqVO pageReqVO); + + // ==================== 采购退货项 ==================== + + /** + * 获得采购退货项列表 + * + * @param returnId 采购退货编号 + * @return 采购退货项列表 + */ + List getPurchaseReturnItemListByReturnId(Long returnId); + + /** + * 获得采购退货项 List + * + * @param returnIds 采购退货编号数组 + * @return 采购退货项 List + */ + List getPurchaseReturnItemListByReturnIds(Collection returnIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java new file mode 100644 index 000000000..83238220c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java @@ -0,0 +1,304 @@ +package cn.iocoder.yudao.module.erp.service.purchase; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns.ErpPurchaseReturnPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns.ErpPurchaseReturnSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseReturnItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseReturnMapper; +import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; +import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockRecordService; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 采购退货 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpPurchaseReturnServiceImpl implements ErpPurchaseReturnService { + + @Resource + private ErpPurchaseReturnMapper purchaseReturnMapper; + @Resource + private ErpPurchaseReturnItemMapper purchaseReturnItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpProductService productService; + @Resource + @Lazy // 延迟加载,避免循环依赖 + private ErpPurchaseOrderService purchaseOrderService; + @Resource + private ErpAccountService accountService; + @Resource + private ErpStockRecordService stockRecordService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createPurchaseReturn(ErpPurchaseReturnSaveReqVO createReqVO) { + // 1.1 校验采购订单已审核 + ErpPurchaseOrderDO purchaseOrder = purchaseOrderService.validatePurchaseOrder(createReqVO.getOrderId()); + // 1.2 校验退货项的有效性 + List purchaseReturnItems = validatePurchaseReturnItems(createReqVO.getItems()); + // 1.3 校验结算账户 + accountService.validateAccount(createReqVO.getAccountId()); + // 1.4 生成退货单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.PURCHASE_RETURN_NO_PREFIX); + if (purchaseReturnMapper.selectByNo(no) != null) { + throw exception(PURCHASE_RETURN_NO_EXISTS); + } + + // 2.1 插入退货 + ErpPurchaseReturnDO purchaseReturn = BeanUtils.toBean(createReqVO, ErpPurchaseReturnDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus())) + .setOrderNo(purchaseOrder.getNo()).setSupplierId(purchaseOrder.getSupplierId()); + calculateTotalPrice(purchaseReturn, purchaseReturnItems); + purchaseReturnMapper.insert(purchaseReturn); + // 2.2 插入退货项 + purchaseReturnItems.forEach(o -> o.setReturnId(purchaseReturn.getId())); + purchaseReturnItemMapper.insertBatch(purchaseReturnItems); + + // 3. 更新采购订单的退货数量 + updatePurchaseOrderReturnCount(createReqVO.getOrderId()); + return purchaseReturn.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updatePurchaseReturn(ErpPurchaseReturnSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpPurchaseReturnDO purchaseReturn = validatePurchaseReturnExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(purchaseReturn.getStatus())) { + throw exception(PURCHASE_RETURN_UPDATE_FAIL_APPROVE, purchaseReturn.getNo()); + } + // 1.2 校验采购订单已审核 + ErpPurchaseOrderDO purchaseOrder = purchaseOrderService.validatePurchaseOrder(updateReqVO.getOrderId()); + // 1.3 校验结算账户 + accountService.validateAccount(updateReqVO.getAccountId()); + // 1.4 校验订单项的有效性 + List purchaseReturnItems = validatePurchaseReturnItems(updateReqVO.getItems()); + + // 2.1 更新退货 + ErpPurchaseReturnDO updateObj = BeanUtils.toBean(updateReqVO, ErpPurchaseReturnDO.class) + .setOrderNo(purchaseOrder.getNo()).setSupplierId(purchaseOrder.getSupplierId()); + calculateTotalPrice(updateObj, purchaseReturnItems); + purchaseReturnMapper.updateById(updateObj); + // 2.2 更新退货项 + updatePurchaseReturnItemList(updateReqVO.getId(), purchaseReturnItems); + + // 3.1 更新采购订单的出库数量 + updatePurchaseOrderReturnCount(updateObj.getOrderId()); + // 3.2 注意:如果采购订单编号变更了,需要更新“老”采购订单的出库数量 + if (ObjectUtil.notEqual(purchaseReturn.getOrderId(), updateObj.getOrderId())) { + updatePurchaseOrderReturnCount(purchaseReturn.getOrderId()); + } + } + + private void calculateTotalPrice(ErpPurchaseReturnDO purchaseReturn, List purchaseReturnItems) { + purchaseReturn.setTotalCount(getSumValue(purchaseReturnItems, ErpPurchaseReturnItemDO::getCount, BigDecimal::add)); + purchaseReturn.setTotalProductPrice(getSumValue(purchaseReturnItems, ErpPurchaseReturnItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)); + purchaseReturn.setTotalTaxPrice(getSumValue(purchaseReturnItems, ErpPurchaseReturnItemDO::getTaxPrice, BigDecimal::add, BigDecimal.ZERO)); + purchaseReturn.setTotalPrice(purchaseReturn.getTotalProductPrice().add(purchaseReturn.getTotalTaxPrice())); + // 计算优惠价格 + if (purchaseReturn.getDiscountPercent() == null) { + purchaseReturn.setDiscountPercent(BigDecimal.ZERO); + } + purchaseReturn.setDiscountPrice(MoneyUtils.priceMultiplyPercent(purchaseReturn.getTotalPrice(), purchaseReturn.getDiscountPercent())); + purchaseReturn.setTotalPrice(purchaseReturn.getTotalPrice().subtract(purchaseReturn.getDiscountPrice().add(purchaseReturn.getOtherPrice()))); + } + + private void updatePurchaseOrderReturnCount(Long orderId) { + // 1.1 查询采购订单对应的采购出库单列表 + List purchaseReturns = purchaseReturnMapper.selectListByOrderId(orderId); + // 1.2 查询对应的采购订单项的退货数量 + Map returnCountMap = purchaseReturnItemMapper.selectOrderItemCountSumMapByReturnIds( + convertList(purchaseReturns, ErpPurchaseReturnDO::getId)); + // 2. 更新采购订单的出库数量 + purchaseOrderService.updatePurchaseOrderReturnCount(orderId, returnCountMap); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updatePurchaseReturnStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpPurchaseReturnDO purchaseReturn = validatePurchaseReturnExists(id); + // 1.2 校验状态 + if (purchaseReturn.getStatus().equals(status)) { + throw exception(approve ? PURCHASE_RETURN_APPROVE_FAIL : PURCHASE_RETURN_PROCESS_FAIL); + } + // 1.3 校验已退款 + if (approve && purchaseReturn.getRefundPrice().compareTo(BigDecimal.ZERO) > 0) { + throw exception(PURCHASE_RETURN_PROCESS_FAIL_EXISTS_REFUND); + } + + // 2. 更新状态 + int updateCount = purchaseReturnMapper.updateByIdAndStatus(id, purchaseReturn.getStatus(), + new ErpPurchaseReturnDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? PURCHASE_RETURN_APPROVE_FAIL : PURCHASE_RETURN_PROCESS_FAIL); + } + + // 3. 变更库存 + List purchaseReturnItems = purchaseReturnItemMapper.selectListByReturnId(id); + Integer bizType = approve ? ErpStockRecordBizTypeEnum.PURCHASE_RETURN.getType() + : ErpStockRecordBizTypeEnum.PURCHASE_RETURN_CANCEL.getType(); + purchaseReturnItems.forEach(purchaseReturnItem -> { + BigDecimal count = approve ? purchaseReturnItem.getCount().negate() : purchaseReturnItem.getCount(); + stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( + purchaseReturnItem.getProductId(), purchaseReturnItem.getWarehouseId(), count, + bizType, purchaseReturnItem.getReturnId(), purchaseReturnItem.getId(), purchaseReturn.getNo())); + }); + } + + @Override + public void updatePurchaseReturnRefundPrice(Long id, BigDecimal refundPrice) { + ErpPurchaseReturnDO purchaseReturn = purchaseReturnMapper.selectById(id); + if (purchaseReturn.getRefundPrice().equals(refundPrice)) { + return; + } + if (refundPrice.compareTo(purchaseReturn.getTotalPrice()) > 0) { + throw exception(PURCHASE_RETURN_FAIL_REFUND_PRICE_EXCEED, refundPrice, purchaseReturn.getTotalPrice()); + } + purchaseReturnMapper.updateById(new ErpPurchaseReturnDO().setId(id).setRefundPrice(refundPrice)); + } + + private List validatePurchaseReturnItems(List list) { + // 1. 校验产品存在 + List productList = productService.validProductList( + convertSet(list, ErpPurchaseReturnSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + // 2. 转化为 ErpPurchaseReturnItemDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, ErpPurchaseReturnItemDO.class, item -> { + item.setProductUnitId(productMap.get(item.getProductId()).getUnitId()); + item.setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())); + if (item.getTotalPrice() == null) { + return; + } + if (item.getTaxPercent() != null) { + item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent())); + } + })); + } + + private void updatePurchaseReturnItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = purchaseReturnItemMapper.selectListByReturnId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setReturnId(id)); + purchaseReturnItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + purchaseReturnItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + purchaseReturnItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpPurchaseReturnItemDO::getId)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deletePurchaseReturn(List ids) { + // 1. 校验不处于已审批 + List purchaseReturns = purchaseReturnMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(purchaseReturns)) { + return; + } + purchaseReturns.forEach(purchaseReturn -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(purchaseReturn.getStatus())) { + throw exception(PURCHASE_RETURN_DELETE_FAIL_APPROVE, purchaseReturn.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + purchaseReturns.forEach(purchaseReturn -> { + // 2.1 删除订单 + purchaseReturnMapper.deleteById(purchaseReturn.getId()); + // 2.2 删除订单项 + purchaseReturnItemMapper.deleteByReturnId(purchaseReturn.getId()); + + // 2.3 更新采购订单的出库数量 + updatePurchaseOrderReturnCount(purchaseReturn.getOrderId()); + }); + + } + + private ErpPurchaseReturnDO validatePurchaseReturnExists(Long id) { + ErpPurchaseReturnDO purchaseReturn = purchaseReturnMapper.selectById(id); + if (purchaseReturn == null) { + throw exception(PURCHASE_RETURN_NOT_EXISTS); + } + return purchaseReturn; + } + + @Override + public ErpPurchaseReturnDO getPurchaseReturn(Long id) { + return purchaseReturnMapper.selectById(id); + } + + @Override + public ErpPurchaseReturnDO validatePurchaseReturn(Long id) { + ErpPurchaseReturnDO purchaseReturn = getPurchaseReturn(id); + if (ObjectUtil.notEqual(purchaseReturn.getStatus(), ErpAuditStatus.APPROVE.getStatus())) { + throw exception(PURCHASE_RETURN_NOT_APPROVE); + } + return purchaseReturn; + } + + @Override + public PageResult getPurchaseReturnPage(ErpPurchaseReturnPageReqVO pageReqVO) { + return purchaseReturnMapper.selectPage(pageReqVO); + } + + // ==================== 采购退货项 ==================== + + @Override + public List getPurchaseReturnItemListByReturnId(Long returnId) { + return purchaseReturnItemMapper.selectListByReturnId(returnId); + } + + @Override + public List getPurchaseReturnItemListByReturnIds(Collection returnIds) { + if (CollUtil.isEmpty(returnIds)) { + return Collections.emptyList(); + } + return purchaseReturnItemMapper.selectListByReturnIds(returnIds); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierService.java new file mode 100644 index 000000000..f1afb6a16 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierService.java @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.erp.service.purchase; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * ERP 供应商 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpSupplierService { + + /** + * 创建供应商 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createSupplier(@Valid ErpSupplierSaveReqVO createReqVO); + + /** + * 更新供应商 + * + * @param updateReqVO 更新信息 + */ + void updateSupplier(@Valid ErpSupplierSaveReqVO updateReqVO); + + /** + * 删除供应商 + * + * @param id 编号 + */ + void deleteSupplier(Long id); + + /** + * 获得供应商 + * + * @param id 编号 + * @return 供应商 + */ + ErpSupplierDO getSupplier(Long id); + + /** + * 校验供应商 + * + * @param id 编号 + * @return 供应商 + */ + ErpSupplierDO validateSupplier(Long id); + + /** + * 获得供应商列表 + * + * @param ids 编号列表 + * @return 供应商列表 + */ + List getSupplierList(Collection ids); + + /** + * 获得供应商 Map + * + * @param ids 编号列表 + * @return 供应商 Map + */ + default Map getSupplierMap(Collection ids) { + return convertMap(getSupplierList(ids), ErpSupplierDO::getId); + } + + /** + * 获得供应商分页 + * + * @param pageReqVO 分页查询 + * @return 供应商分页 + */ + PageResult getSupplierPage(ErpSupplierPageReqVO pageReqVO); + + /** + * 获得指定状态的供应商列表 + * + * @param status 状态 + * @return 供应商列表 + */ + List getSupplierListByStatus(Integer status); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java new file mode 100644 index 000000000..af6f2ac23 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.erp.service.purchase; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; +import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpSupplierMapper; +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.erp.enums.ErrorCodeConstants.SUPPLIER_NOT_ENABLE; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.SUPPLIER_NOT_EXISTS; + +/** + * ERP 供应商 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpSupplierServiceImpl implements ErpSupplierService { + + @Resource + private ErpSupplierMapper supplierMapper; + + @Override + public Long createSupplier(ErpSupplierSaveReqVO createReqVO) { + ErpSupplierDO supplier = BeanUtils.toBean(createReqVO, ErpSupplierDO.class); + supplierMapper.insert(supplier); + return supplier.getId(); + } + + @Override + public void updateSupplier(ErpSupplierSaveReqVO updateReqVO) { + // 校验存在 + validateSupplierExists(updateReqVO.getId()); + // 更新 + ErpSupplierDO updateObj = BeanUtils.toBean(updateReqVO, ErpSupplierDO.class); + supplierMapper.updateById(updateObj); + } + + @Override + public void deleteSupplier(Long id) { + // 校验存在 + validateSupplierExists(id); + // 删除 + supplierMapper.deleteById(id); + } + + private void validateSupplierExists(Long id) { + if (supplierMapper.selectById(id) == null) { + throw exception(SUPPLIER_NOT_EXISTS); + } + } + + @Override + public ErpSupplierDO getSupplier(Long id) { + return supplierMapper.selectById(id); + } + + @Override + public ErpSupplierDO validateSupplier(Long id) { + ErpSupplierDO supplier = supplierMapper.selectById(id); + if (supplier == null) { + throw exception(SUPPLIER_NOT_EXISTS); + } + if (CommonStatusEnum.isDisable(supplier.getStatus())) { + throw exception(SUPPLIER_NOT_ENABLE, supplier.getName()); + } + return supplier; + } + + @Override + public List getSupplierList(Collection ids) { + return supplierMapper.selectBatchIds(ids); + } + + @Override + public PageResult getSupplierPage(ErpSupplierPageReqVO pageReqVO) { + return supplierMapper.selectPage(pageReqVO); + } + + @Override + public List getSupplierListByStatus(Integer status) { + return supplierMapper.selectListByStatus(status); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerService.java new file mode 100644 index 000000000..e70c09039 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerService.java @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.erp.service.sale; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * ERP 客户 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpCustomerService { + + /** + * 创建客户 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createCustomer(@Valid ErpCustomerSaveReqVO createReqVO); + + /** + * 更新客户 + * + * @param updateReqVO 更新信息 + */ + void updateCustomer(@Valid ErpCustomerSaveReqVO updateReqVO); + + /** + * 删除客户 + * + * @param id 编号 + */ + void deleteCustomer(Long id); + + /** + * 获得客户 + * + * @param id 编号 + * @return 客户 + */ + ErpCustomerDO getCustomer(Long id); + + /** + * 校验客户 + * + * @param id 编号 + * @return 客户 + */ + ErpCustomerDO validateCustomer(Long id); + + /** + * 获得客户列表 + * + * @param ids 编号列表 + * @return 客户列表 + */ + List getCustomerList(Collection ids); + + /** + * 获得客户 Map + * + * @param ids 编号列表 + * @return 客户 Map + */ + default Map getCustomerMap(Collection ids) { + return convertMap(getCustomerList(ids), ErpCustomerDO::getId); + } + + /** + * 获得客户分页 + * + * @param pageReqVO 分页查询 + * @return 客户分页 + */ + PageResult getCustomerPage(ErpCustomerPageReqVO pageReqVO); + + /** + * 获得指定状态的客户列表 + * + * @param status 状态 + * @return 客户列表 + */ + List getCustomerListByStatus(Integer status); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImpl.java new file mode 100644 index 000000000..7df07fb39 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImpl.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.erp.service.sale; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; +import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpCustomerMapper; +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.erp.enums.ErrorCodeConstants.CUSTOMER_NOT_ENABLE; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS; + +/** + * ERP 客户 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpCustomerServiceImpl implements ErpCustomerService { + + @Resource + private ErpCustomerMapper customerMapper; + + @Override + public Long createCustomer(ErpCustomerSaveReqVO createReqVO) { + // 插入 + ErpCustomerDO customer = BeanUtils.toBean(createReqVO, ErpCustomerDO.class); + customerMapper.insert(customer); + // 返回 + return customer.getId(); + } + + @Override + public void updateCustomer(ErpCustomerSaveReqVO updateReqVO) { + // 校验存在 + validateCustomerExists(updateReqVO.getId()); + // 更新 + ErpCustomerDO updateObj = BeanUtils.toBean(updateReqVO, ErpCustomerDO.class); + customerMapper.updateById(updateObj); + } + + @Override + public void deleteCustomer(Long id) { + // 校验存在 + validateCustomerExists(id); + // 删除 + customerMapper.deleteById(id); + } + + private void validateCustomerExists(Long id) { + if (customerMapper.selectById(id) == null) { + throw exception(CUSTOMER_NOT_EXISTS); + } + } + + @Override + public ErpCustomerDO getCustomer(Long id) { + return customerMapper.selectById(id); + } + + @Override + public ErpCustomerDO validateCustomer(Long id) { + ErpCustomerDO customer = customerMapper.selectById(id); + if (customer == null) { + throw exception(CUSTOMER_NOT_EXISTS); + } + if (CommonStatusEnum.isDisable(customer.getStatus())) { + throw exception(CUSTOMER_NOT_ENABLE, customer.getName()); + } + return customer; + } + + @Override + public List getCustomerList(Collection ids) { + return customerMapper.selectBatchIds(ids); + } + + @Override + public PageResult getCustomerPage(ErpCustomerPageReqVO pageReqVO) { + return customerMapper.selectPage(pageReqVO); + } + + @Override + public List getCustomerListByStatus(Integer status) { + return customerMapper.selectListByStatus(status); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java new file mode 100644 index 000000000..dad08944b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java @@ -0,0 +1,110 @@ +package cn.iocoder.yudao.module.erp.service.sale; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderItemDO; + +import javax.validation.Valid; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * ERP 销售订单 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpSaleOrderService { + + /** + * 创建销售订单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createSaleOrder(@Valid ErpSaleOrderSaveReqVO createReqVO); + + /** + * 更新销售订单 + * + * @param updateReqVO 更新信息 + */ + void updateSaleOrder(@Valid ErpSaleOrderSaveReqVO updateReqVO); + + /** + * 更新销售订单的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updateSaleOrderStatus(Long id, Integer status); + + /** + * 更新销售订单的出库数量 + * + * @param id 编号 + * @param outCountMap 出库数量 Map:key 销售订单项编号;value 出库数量 + */ + void updateSaleOrderOutCount(Long id, Map outCountMap); + + /** + * 更新销售订单的退货数量 + * + * @param orderId 编号 + * @param returnCountMap 退货数量 Map:key 销售订单项编号;value 退货数量 + */ + void updateSaleOrderReturnCount(Long orderId, Map returnCountMap); + + /** + * 删除销售订单 + * + * @param ids 编号数组 + */ + void deleteSaleOrder(List ids); + + /** + * 获得销售订单 + * + * @param id 编号 + * @return 销售订单 + */ + ErpSaleOrderDO getSaleOrder(Long id); + + /** + * 校验销售订单,已经审核通过 + * + * @param id 编号 + * @return 销售订单 + */ + ErpSaleOrderDO validateSaleOrder(Long id); + + /** + * 获得销售订单分页 + * + * @param pageReqVO 分页查询 + * @return 销售订单分页 + */ + PageResult getSaleOrderPage(ErpSaleOrderPageReqVO pageReqVO); + + // ==================== 销售订单项 ==================== + + /** + * 获得销售订单项列表 + * + * @param orderId 销售订单编号 + * @return 销售订单项列表 + */ + List getSaleOrderItemListByOrderId(Long orderId); + + /** + * 获得销售订单项 List + * + * @param orderIds 销售订单编号数组 + * @return 销售订单项 List + */ + List getSaleOrderItemListByOrderIds(Collection orderIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java new file mode 100644 index 000000000..7c25d067e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java @@ -0,0 +1,307 @@ +package cn.iocoder.yudao.module.erp.service.sale; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOrderItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOrderMapper; +import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 销售订单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { + + @Resource + private ErpSaleOrderMapper saleOrderMapper; + @Resource + private ErpSaleOrderItemMapper saleOrderItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpProductService productService; + @Resource + private ErpCustomerService customerService; + @Resource + private ErpAccountService accountService; + + @Resource + private AdminUserApi adminUserApi; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createSaleOrder(ErpSaleOrderSaveReqVO createReqVO) { + // 1.1 校验订单项的有效性 + List saleOrderItems = validateSaleOrderItems(createReqVO.getItems()); + // 1.2 校验客户 + customerService.validateCustomer(createReqVO.getCustomerId()); + // 1.3 校验结算账户 + if (createReqVO.getAccountId() != null) { + accountService.validateAccount(createReqVO.getAccountId()); + } + // 1.4 校验销售人员 + if (createReqVO.getSaleUserId() != null) { + adminUserApi.validateUser(createReqVO.getSaleUserId()); + } + // 1.5 生成订单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.SALE_ORDER_NO_PREFIX); + if (saleOrderMapper.selectByNo(no) != null) { + throw exception(SALE_ORDER_NO_EXISTS); + } + + // 2.1 插入订单 + ErpSaleOrderDO saleOrder = BeanUtils.toBean(createReqVO, ErpSaleOrderDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus())); + calculateTotalPrice(saleOrder, saleOrderItems); + saleOrderMapper.insert(saleOrder); + // 2.2 插入订单项 + saleOrderItems.forEach(o -> o.setOrderId(saleOrder.getId())); + saleOrderItemMapper.insertBatch(saleOrderItems); + return saleOrder.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateSaleOrder(ErpSaleOrderSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpSaleOrderDO saleOrder = validateSaleOrderExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(saleOrder.getStatus())) { + throw exception(SALE_ORDER_UPDATE_FAIL_APPROVE, saleOrder.getNo()); + } + // 1.2 校验客户 + customerService.validateCustomer(updateReqVO.getCustomerId()); + // 1.3 校验结算账户 + if (updateReqVO.getAccountId() != null) { + accountService.validateAccount(updateReqVO.getAccountId()); + } + // 1.4 校验销售人员 + if (updateReqVO.getSaleUserId() != null) { + adminUserApi.validateUser(updateReqVO.getSaleUserId()); + } + // 1.5 校验订单项的有效性 + List saleOrderItems = validateSaleOrderItems(updateReqVO.getItems()); + + // 2.1 更新订单 + ErpSaleOrderDO updateObj = BeanUtils.toBean(updateReqVO, ErpSaleOrderDO.class); + calculateTotalPrice(updateObj, saleOrderItems); + saleOrderMapper.updateById(updateObj); + // 2.2 更新订单项 + updateSaleOrderItemList(updateReqVO.getId(), saleOrderItems); + } + + private void calculateTotalPrice(ErpSaleOrderDO saleOrder, List saleOrderItems) { + saleOrder.setTotalCount(getSumValue(saleOrderItems, ErpSaleOrderItemDO::getCount, BigDecimal::add)); + saleOrder.setTotalProductPrice(getSumValue(saleOrderItems, ErpSaleOrderItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)); + saleOrder.setTotalTaxPrice(getSumValue(saleOrderItems, ErpSaleOrderItemDO::getTaxPrice, BigDecimal::add, BigDecimal.ZERO)); + saleOrder.setTotalPrice(saleOrder.getTotalProductPrice().add(saleOrder.getTotalTaxPrice())); + // 计算优惠价格 + if (saleOrder.getDiscountPercent() == null) { + saleOrder.setDiscountPercent(BigDecimal.ZERO); + } + saleOrder.setDiscountPrice(MoneyUtils.priceMultiplyPercent(saleOrder.getTotalPrice(), saleOrder.getDiscountPercent())); + saleOrder.setTotalPrice(saleOrder.getTotalPrice().subtract(saleOrder.getDiscountPrice())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateSaleOrderStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpSaleOrderDO saleOrder = validateSaleOrderExists(id); + // 1.2 校验状态 + if (saleOrder.getStatus().equals(status)) { + throw exception(approve ? SALE_ORDER_APPROVE_FAIL : SALE_ORDER_PROCESS_FAIL); + } + // 1.3 存在销售出库单,无法反审核 + if (!approve && saleOrder.getOutCount().compareTo(BigDecimal.ZERO) > 0) { + throw exception(SALE_ORDER_PROCESS_FAIL_EXISTS_OUT); + } + // 1.4 存在销售退货单,无法反审核 + if (!approve && saleOrder.getReturnCount().compareTo(BigDecimal.ZERO) > 0) { + throw exception(SALE_ORDER_PROCESS_FAIL_EXISTS_RETURN); + } + + // 2. 更新状态 + int updateCount = saleOrderMapper.updateByIdAndStatus(id, saleOrder.getStatus(), + new ErpSaleOrderDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? SALE_ORDER_APPROVE_FAIL : SALE_ORDER_PROCESS_FAIL); + } + } + + private List validateSaleOrderItems(List list) { + // 1. 校验产品存在 + List productList = productService.validProductList( + convertSet(list, ErpSaleOrderSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + // 2. 转化为 ErpSaleOrderItemDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, ErpSaleOrderItemDO.class, item -> { + item.setProductUnitId(productMap.get(item.getProductId()).getUnitId()); + item.setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())); + if (item.getTotalPrice() == null) { + return; + } + if (item.getTaxPercent() != null) { + item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent())); + } + })); + } + + private void updateSaleOrderItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = saleOrderItemMapper.selectListByOrderId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setOrderId(id)); + saleOrderItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + saleOrderItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + saleOrderItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpSaleOrderItemDO::getId)); + } + } + + @Override + public void updateSaleOrderOutCount(Long id, Map outCountMap) { + List orderItems = saleOrderItemMapper.selectListByOrderId(id); + // 1. 更新每个销售订单项 + orderItems.forEach(item -> { + BigDecimal outCount = outCountMap.getOrDefault(item.getId(), BigDecimal.ZERO); + if (item.getOutCount().equals(outCount)) { + return; + } + if (outCount.compareTo(item.getCount()) > 0) { + throw exception(SALE_ORDER_ITEM_OUT_FAIL_PRODUCT_EXCEED, + productService.getProduct(item.getProductId()).getName(), item.getCount()); + } + saleOrderItemMapper.updateById(new ErpSaleOrderItemDO().setId(item.getId()).setOutCount(outCount)); + }); + // 2. 更新销售订单 + BigDecimal totalOutCount = getSumValue(outCountMap.values(), value -> value, BigDecimal::add, BigDecimal.ZERO); + saleOrderMapper.updateById(new ErpSaleOrderDO().setId(id).setOutCount(totalOutCount)); + } + + @Override + public void updateSaleOrderReturnCount(Long orderId, Map returnCountMap) { + List orderItems = saleOrderItemMapper.selectListByOrderId(orderId); + // 1. 更新每个销售订单项 + orderItems.forEach(item -> { + BigDecimal returnCount = returnCountMap.getOrDefault(item.getId(), BigDecimal.ZERO); + if (item.getReturnCount().equals(returnCount)) { + return; + } + if (returnCount.compareTo(item.getOutCount()) > 0) { + throw exception(SALE_ORDER_ITEM_RETURN_FAIL_OUT_EXCEED, + productService.getProduct(item.getProductId()).getName(), item.getOutCount()); + } + saleOrderItemMapper.updateById(new ErpSaleOrderItemDO().setId(item.getId()).setReturnCount(returnCount)); + }); + // 2. 更新销售订单 + BigDecimal totalReturnCount = getSumValue(returnCountMap.values(), value -> value, BigDecimal::add, BigDecimal.ZERO); + saleOrderMapper.updateById(new ErpSaleOrderDO().setId(orderId).setReturnCount(totalReturnCount)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteSaleOrder(List ids) { + // 1. 校验不处于已审批 + List saleOrders = saleOrderMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(saleOrders)) { + return; + } + saleOrders.forEach(saleOrder -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(saleOrder.getStatus())) { + throw exception(SALE_ORDER_DELETE_FAIL_APPROVE, saleOrder.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + saleOrders.forEach(saleOrder -> { + // 2.1 删除订单 + saleOrderMapper.deleteById(saleOrder.getId()); + // 2.2 删除订单项 + saleOrderItemMapper.deleteByOrderId(saleOrder.getId()); + }); + } + + private ErpSaleOrderDO validateSaleOrderExists(Long id) { + ErpSaleOrderDO saleOrder = saleOrderMapper.selectById(id); + if (saleOrder == null) { + throw exception(SALE_ORDER_NOT_EXISTS); + } + return saleOrder; + } + + @Override + public ErpSaleOrderDO getSaleOrder(Long id) { + return saleOrderMapper.selectById(id); + } + + @Override + public ErpSaleOrderDO validateSaleOrder(Long id) { + ErpSaleOrderDO saleOrder = validateSaleOrderExists(id); + if (ObjectUtil.notEqual(saleOrder.getStatus(), ErpAuditStatus.APPROVE.getStatus())) { + throw exception(SALE_ORDER_NOT_APPROVE); + } + return saleOrder; + } + + @Override + public PageResult getSaleOrderPage(ErpSaleOrderPageReqVO pageReqVO) { + return saleOrderMapper.selectPage(pageReqVO); + } + + // ==================== 订单项 ==================== + + @Override + public List getSaleOrderItemListByOrderId(Long orderId) { + return saleOrderItemMapper.selectListByOrderId(orderId); + } + + @Override + public List getSaleOrderItemListByOrderIds(Collection orderIds) { + if (CollUtil.isEmpty(orderIds)) { + return Collections.emptyList(); + } + return saleOrderItemMapper.selectListByOrderIds(orderIds); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutService.java new file mode 100644 index 000000000..a57f013fc --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutService.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.erp.service.sale; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out.ErpSaleOutPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out.ErpSaleOutSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutItemDO; + +import javax.validation.Valid; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.List; + +/** + * ERP 销售出库 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpSaleOutService { + + /** + * 创建销售出库 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createSaleOut(@Valid ErpSaleOutSaveReqVO createReqVO); + + /** + * 更新销售出库 + * + * @param updateReqVO 更新信息 + */ + void updateSaleOut(@Valid ErpSaleOutSaveReqVO updateReqVO); + + /** + * 更新销售出库的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updateSaleOutStatus(Long id, Integer status); + + /** + * 更新销售出库的收款金额 + * + * @param id 编号 + * @param receiptPrice 收款金额 + */ + void updateSaleInReceiptPrice(Long id, BigDecimal receiptPrice); + + /** + * 删除销售出库 + * + * @param ids 编号数组 + */ + void deleteSaleOut(List ids); + + /** + * 获得销售出库 + * + * @param id 编号 + * @return 销售出库 + */ + ErpSaleOutDO getSaleOut(Long id); + + /** + * 校验销售出库,已经审核通过 + * + * @param id 编号 + * @return 销售出库 + */ + ErpSaleOutDO validateSaleOut(Long id); + + /** + * 获得销售出库分页 + * + * @param pageReqVO 分页查询 + * @return 销售出库分页 + */ + PageResult getSaleOutPage(ErpSaleOutPageReqVO pageReqVO); + + // ==================== 销售出库项 ==================== + + /** + * 获得销售出库项列表 + * + * @param outId 销售出库编号 + * @return 销售出库项列表 + */ + List getSaleOutItemListByOutId(Long outId); + + /** + * 获得销售出库项 List + * + * @param outIds 销售出库编号数组 + * @return 销售出库项 List + */ + List getSaleOutItemListByOutIds(Collection outIds); + + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java new file mode 100644 index 000000000..3cd476912 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java @@ -0,0 +1,316 @@ +package cn.iocoder.yudao.module.erp.service.sale; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out.ErpSaleOutPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out.ErpSaleOutSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOutItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOutMapper; +import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; +import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockRecordService; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 销售出库 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpSaleOutServiceImpl implements ErpSaleOutService { + + @Resource + private ErpSaleOutMapper saleOutMapper; + @Resource + private ErpSaleOutItemMapper saleOutItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpProductService productService; + @Resource + @Lazy // 延迟加载,避免循环依赖 + private ErpSaleOrderService saleOrderService; + @Resource + private ErpAccountService accountService; + @Resource + private ErpStockRecordService stockRecordService; + + @Resource + private AdminUserApi adminUserApi; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createSaleOut(ErpSaleOutSaveReqVO createReqVO) { + // 1.1 校验销售订单已审核 + ErpSaleOrderDO saleOrder = saleOrderService.validateSaleOrder(createReqVO.getOrderId()); + // 1.2 校验出库项的有效性 + List saleOutItems = validateSaleOutItems(createReqVO.getItems()); + // 1.3 校验结算账户 + accountService.validateAccount(createReqVO.getAccountId()); + // 1.4 校验销售人员 + if (createReqVO.getSaleUserId() != null) { + adminUserApi.validateUser(createReqVO.getSaleUserId()); + } + // 1.5 生成出库单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.SALE_OUT_NO_PREFIX); + if (saleOutMapper.selectByNo(no) != null) { + throw exception(SALE_OUT_NO_EXISTS); + } + + // 2.1 插入出库 + ErpSaleOutDO saleOut = BeanUtils.toBean(createReqVO, ErpSaleOutDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus())) + .setOrderNo(saleOrder.getNo()).setCustomerId(saleOrder.getCustomerId()); + calculateTotalPrice(saleOut, saleOutItems); + saleOutMapper.insert(saleOut); + // 2.2 插入出库项 + saleOutItems.forEach(o -> o.setOutId(saleOut.getId())); + saleOutItemMapper.insertBatch(saleOutItems); + + // 3. 更新销售订单的出库数量 + updateSaleOrderOutCount(createReqVO.getOrderId()); + return saleOut.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateSaleOut(ErpSaleOutSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpSaleOutDO saleOut = validateSaleOutExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(saleOut.getStatus())) { + throw exception(SALE_OUT_UPDATE_FAIL_APPROVE, saleOut.getNo()); + } + // 1.2 校验销售订单已审核 + ErpSaleOrderDO saleOrder = saleOrderService.validateSaleOrder(updateReqVO.getOrderId()); + // 1.3 校验结算账户 + accountService.validateAccount(updateReqVO.getAccountId()); + // 1.4 校验销售人员 + if (updateReqVO.getSaleUserId() != null) { + adminUserApi.validateUser(updateReqVO.getSaleUserId()); + } + // 1.5 校验订单项的有效性 + List saleOutItems = validateSaleOutItems(updateReqVO.getItems()); + + // 2.1 更新出库 + ErpSaleOutDO updateObj = BeanUtils.toBean(updateReqVO, ErpSaleOutDO.class) + .setOrderNo(saleOrder.getNo()).setCustomerId(saleOrder.getCustomerId()); + calculateTotalPrice(updateObj, saleOutItems); + saleOutMapper.updateById(updateObj); + // 2.2 更新出库项 + updateSaleOutItemList(updateReqVO.getId(), saleOutItems); + + // 3.1 更新销售订单的出库数量 + updateSaleOrderOutCount(updateObj.getOrderId()); + // 3.2 注意:如果销售订单编号变更了,需要更新“老”销售订单的出库数量 + if (ObjectUtil.notEqual(saleOut.getOrderId(), updateObj.getOrderId())) { + updateSaleOrderOutCount(saleOut.getOrderId()); + } + } + + private void calculateTotalPrice(ErpSaleOutDO saleOut, List saleOutItems) { + saleOut.setTotalCount(getSumValue(saleOutItems, ErpSaleOutItemDO::getCount, BigDecimal::add)); + saleOut.setTotalProductPrice(getSumValue(saleOutItems, ErpSaleOutItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)); + saleOut.setTotalTaxPrice(getSumValue(saleOutItems, ErpSaleOutItemDO::getTaxPrice, BigDecimal::add, BigDecimal.ZERO)); + saleOut.setTotalPrice(saleOut.getTotalProductPrice().add(saleOut.getTotalTaxPrice())); + // 计算优惠价格 + if (saleOut.getDiscountPercent() == null) { + saleOut.setDiscountPercent(BigDecimal.ZERO); + } + saleOut.setDiscountPrice(MoneyUtils.priceMultiplyPercent(saleOut.getTotalPrice(), saleOut.getDiscountPercent())); + saleOut.setTotalPrice(saleOut.getTotalPrice().subtract(saleOut.getDiscountPrice().add(saleOut.getOtherPrice()))); + } + + private void updateSaleOrderOutCount(Long orderId) { + // 1.1 查询销售订单对应的销售出库单列表 + List saleOuts = saleOutMapper.selectListByOrderId(orderId); + // 1.2 查询对应的销售订单项的出库数量 + Map returnCountMap = saleOutItemMapper.selectOrderItemCountSumMapByOutIds( + convertList(saleOuts, ErpSaleOutDO::getId)); + // 2. 更新销售订单的出库数量 + saleOrderService.updateSaleOrderOutCount(orderId, returnCountMap); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateSaleOutStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpSaleOutDO saleOut = validateSaleOutExists(id); + // 1.2 校验状态 + if (saleOut.getStatus().equals(status)) { + throw exception(approve ? SALE_OUT_APPROVE_FAIL : SALE_OUT_PROCESS_FAIL); + } + // 1.3 校验已退款 + if (approve && saleOut.getReceiptPrice().compareTo(BigDecimal.ZERO) > 0) { + throw exception(SALE_OUT_PROCESS_FAIL_EXISTS_RECEIPT); + } + + // 2. 更新状态 + int updateCount = saleOutMapper.updateByIdAndStatus(id, saleOut.getStatus(), + new ErpSaleOutDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? SALE_OUT_APPROVE_FAIL : SALE_OUT_PROCESS_FAIL); + } + + // 3. 变更库存 + List saleOutItems = saleOutItemMapper.selectListByOutId(id); + Integer bizType = approve ? ErpStockRecordBizTypeEnum.SALE_OUT.getType() + : ErpStockRecordBizTypeEnum.SALE_OUT_CANCEL.getType(); + saleOutItems.forEach(saleOutItem -> { + BigDecimal count = approve ? saleOutItem.getCount().negate() : saleOutItem.getCount(); + stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( + saleOutItem.getProductId(), saleOutItem.getWarehouseId(), count, + bizType, saleOutItem.getOutId(), saleOutItem.getId(), saleOut.getNo())); + }); + } + + @Override + public void updateSaleInReceiptPrice(Long id, BigDecimal receiptPrice) { + ErpSaleOutDO saleOut = saleOutMapper.selectById(id); + if (saleOut.getReceiptPrice().equals(receiptPrice)) { + return; + } + if (receiptPrice.compareTo(saleOut.getTotalPrice()) > 0) { + throw exception(SALE_OUT_FAIL_RECEIPT_PRICE_EXCEED, receiptPrice, saleOut.getTotalPrice()); + } + saleOutMapper.updateById(new ErpSaleOutDO().setId(id).setReceiptPrice(receiptPrice)); + } + + private List validateSaleOutItems(List list) { + // 1. 校验产品存在 + List productList = productService.validProductList( + convertSet(list, ErpSaleOutSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + // 2. 转化为 ErpSaleOutItemDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, ErpSaleOutItemDO.class, item -> { + item.setProductUnitId(productMap.get(item.getProductId()).getUnitId()); + item.setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())); + if (item.getTotalPrice() == null) { + return; + } + if (item.getTaxPercent() != null) { + item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent())); + } + })); + } + + private void updateSaleOutItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = saleOutItemMapper.selectListByOutId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setOutId(id)); + saleOutItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + saleOutItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + saleOutItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpSaleOutItemDO::getId)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteSaleOut(List ids) { + // 1. 校验不处于已审批 + List saleOuts = saleOutMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(saleOuts)) { + return; + } + saleOuts.forEach(saleOut -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(saleOut.getStatus())) { + throw exception(SALE_OUT_DELETE_FAIL_APPROVE, saleOut.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + saleOuts.forEach(saleOut -> { + // 2.1 删除订单 + saleOutMapper.deleteById(saleOut.getId()); + // 2.2 删除订单项 + saleOutItemMapper.deleteByOutId(saleOut.getId()); + + // 2.3 更新销售订单的出库数量 + updateSaleOrderOutCount(saleOut.getOrderId()); + }); + + } + + private ErpSaleOutDO validateSaleOutExists(Long id) { + ErpSaleOutDO saleOut = saleOutMapper.selectById(id); + if (saleOut == null) { + throw exception(SALE_OUT_NOT_EXISTS); + } + return saleOut; + } + + @Override + public ErpSaleOutDO getSaleOut(Long id) { + return saleOutMapper.selectById(id); + } + + @Override + public ErpSaleOutDO validateSaleOut(Long id) { + ErpSaleOutDO saleOut = validateSaleOutExists(id); + if (ObjectUtil.notEqual(saleOut.getStatus(), ErpAuditStatus.APPROVE.getStatus())) { + throw exception(SALE_OUT_NOT_APPROVE); + } + return saleOut; + } + + @Override + public PageResult getSaleOutPage(ErpSaleOutPageReqVO pageReqVO) { + return saleOutMapper.selectPage(pageReqVO); + } + + // ==================== 销售出库项 ==================== + + @Override + public List getSaleOutItemListByOutId(Long outId) { + return saleOutItemMapper.selectListByOutId(outId); + } + + @Override + public List getSaleOutItemListByOutIds(Collection outIds) { + if (CollUtil.isEmpty(outIds)) { + return Collections.emptyList(); + } + return saleOutItemMapper.selectListByOutIds(outIds); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnService.java new file mode 100644 index 000000000..6f18dc07c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnService.java @@ -0,0 +1,101 @@ +package cn.iocoder.yudao.module.erp.service.sale; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns.ErpSaleReturnPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns.ErpSaleReturnSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnItemDO; + +import javax.validation.Valid; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.List; + +/** + * ERP 销售退货 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpSaleReturnService { + + /** + * 创建销售退货 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createSaleReturn(@Valid ErpSaleReturnSaveReqVO createReqVO); + + /** + * 更新销售退货 + * + * @param updateReqVO 更新信息 + */ + void updateSaleReturn(@Valid ErpSaleReturnSaveReqVO updateReqVO); + + /** + * 更新销售退货的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updateSaleReturnStatus(Long id, Integer status); + + /** + * 更新销售退货的退款金额 + * + * @param id 编号 + * @param refundPrice 退款金额 + */ + void updateSaleReturnRefundPrice(Long id, BigDecimal refundPrice); + + /** + * 删除销售退货 + * + * @param ids 编号数组 + */ + void deleteSaleReturn(List ids); + + /** + * 获得销售退货 + * + * @param id 编号 + * @return 销售退货 + */ + ErpSaleReturnDO getSaleReturn(Long id); + + /** + * 校验销售退货,已经审核通过 + * + * @param id 编号 + * @return 销售退货 + */ + ErpSaleReturnDO validateSaleReturn(Long id); + + /** + * 获得销售退货分页 + * + * @param pageReqVO 分页查询 + * @return 销售退货分页 + */ + PageResult getSaleReturnPage(ErpSaleReturnPageReqVO pageReqVO); + + // ==================== 销售退货项 ==================== + + /** + * 获得销售退货项列表 + * + * @param returnId 销售退货编号 + * @return 销售退货项列表 + */ + List getSaleReturnItemListByReturnId(Long returnId); + + /** + * 获得销售退货项 List + * + * @param returnIds 销售退货编号数组 + * @return 销售退货项 List + */ + List getSaleReturnItemListByReturnIds(Collection returnIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java new file mode 100644 index 000000000..a10a73ad1 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java @@ -0,0 +1,316 @@ +package cn.iocoder.yudao.module.erp.service.sale; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns.ErpSaleReturnPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns.ErpSaleReturnSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleReturnItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleReturnMapper; +import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; +import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockRecordService; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 销售退货 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpSaleReturnServiceImpl implements ErpSaleReturnService { + + @Resource + private ErpSaleReturnMapper saleReturnMapper; + @Resource + private ErpSaleReturnItemMapper saleReturnItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpProductService productService; + @Resource + @Lazy // 延迟加载,避免循环依赖 + private ErpSaleOrderService saleOrderService; + @Resource + private ErpAccountService accountService; + @Resource + private ErpStockRecordService stockRecordService; + + @Resource + private AdminUserApi adminUserApi; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createSaleReturn(ErpSaleReturnSaveReqVO createReqVO) { + // 1.1 校验销售订单已审核 + ErpSaleOrderDO saleOrder = saleOrderService.validateSaleOrder(createReqVO.getOrderId()); + // 1.2 校验退货项的有效性 + List saleReturnItems = validateSaleReturnItems(createReqVO.getItems()); + // 1.3 校验结算账户 + accountService.validateAccount(createReqVO.getAccountId()); + // 1.4 校验销售人员 + if (createReqVO.getSaleUserId() != null) { + adminUserApi.validateUser(createReqVO.getSaleUserId()); + } + // 1.5 生成退货单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.SALE_RETURN_NO_PREFIX); + if (saleReturnMapper.selectByNo(no) != null) { + throw exception(SALE_RETURN_NO_EXISTS); + } + + // 2.1 插入退货 + ErpSaleReturnDO saleReturn = BeanUtils.toBean(createReqVO, ErpSaleReturnDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus())) + .setOrderNo(saleOrder.getNo()).setCustomerId(saleOrder.getCustomerId()); + calculateTotalPrice(saleReturn, saleReturnItems); + saleReturnMapper.insert(saleReturn); + // 2.2 插入退货项 + saleReturnItems.forEach(o -> o.setReturnId(saleReturn.getId())); + saleReturnItemMapper.insertBatch(saleReturnItems); + + // 3. 更新销售订单的退货数量 + updateSaleOrderReturnCount(createReqVO.getOrderId()); + return saleReturn.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateSaleReturn(ErpSaleReturnSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpSaleReturnDO saleReturn = validateSaleReturnExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(saleReturn.getStatus())) { + throw exception(SALE_RETURN_UPDATE_FAIL_APPROVE, saleReturn.getNo()); + } + // 1.2 校验销售订单已审核 + ErpSaleOrderDO saleOrder = saleOrderService.validateSaleOrder(updateReqVO.getOrderId()); + // 1.3 校验结算账户 + accountService.validateAccount(updateReqVO.getAccountId()); + // 1.4 校验销售人员 + if (updateReqVO.getSaleUserId() != null) { + adminUserApi.validateUser(updateReqVO.getSaleUserId()); + } + // 1.5 校验订单项的有效性 + List saleReturnItems = validateSaleReturnItems(updateReqVO.getItems()); + + // 2.1 更新退货 + ErpSaleReturnDO updateObj = BeanUtils.toBean(updateReqVO, ErpSaleReturnDO.class) + .setOrderNo(saleOrder.getNo()).setCustomerId(saleOrder.getCustomerId()); + calculateTotalPrice(updateObj, saleReturnItems); + saleReturnMapper.updateById(updateObj); + // 2.2 更新退货项 + updateSaleReturnItemList(updateReqVO.getId(), saleReturnItems); + + // 3.1 更新销售订单的出库数量 + updateSaleOrderReturnCount(updateObj.getOrderId()); + // 3.2 注意:如果销售订单编号变更了,需要更新“老”销售订单的出库数量 + if (ObjectUtil.notEqual(saleReturn.getOrderId(), updateObj.getOrderId())) { + updateSaleOrderReturnCount(saleReturn.getOrderId()); + } + } + + private void calculateTotalPrice(ErpSaleReturnDO saleReturn, List saleReturnItems) { + saleReturn.setTotalCount(getSumValue(saleReturnItems, ErpSaleReturnItemDO::getCount, BigDecimal::add)); + saleReturn.setTotalProductPrice(getSumValue(saleReturnItems, ErpSaleReturnItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)); + saleReturn.setTotalTaxPrice(getSumValue(saleReturnItems, ErpSaleReturnItemDO::getTaxPrice, BigDecimal::add, BigDecimal.ZERO)); + saleReturn.setTotalPrice(saleReturn.getTotalProductPrice().add(saleReturn.getTotalTaxPrice())); + // 计算优惠价格 + if (saleReturn.getDiscountPercent() == null) { + saleReturn.setDiscountPercent(BigDecimal.ZERO); + } + saleReturn.setDiscountPrice(MoneyUtils.priceMultiplyPercent(saleReturn.getTotalPrice(), saleReturn.getDiscountPercent())); + saleReturn.setTotalPrice(saleReturn.getTotalPrice().subtract(saleReturn.getDiscountPrice().add(saleReturn.getOtherPrice()))); + } + + private void updateSaleOrderReturnCount(Long orderId) { + // 1.1 查询销售订单对应的销售出库单列表 + List saleReturns = saleReturnMapper.selectListByOrderId(orderId); + // 1.2 查询对应的销售订单项的退货数量 + Map returnCountMap = saleReturnItemMapper.selectOrderItemCountSumMapByReturnIds( + convertList(saleReturns, ErpSaleReturnDO::getId)); + // 2. 更新销售订单的出库数量 + saleOrderService.updateSaleOrderReturnCount(orderId, returnCountMap); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateSaleReturnStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpSaleReturnDO saleReturn = validateSaleReturnExists(id); + // 1.2 校验状态 + if (saleReturn.getStatus().equals(status)) { + throw exception(approve ? SALE_RETURN_APPROVE_FAIL : SALE_RETURN_PROCESS_FAIL); + } + // 1.3 校验已退款 + if (approve && saleReturn.getRefundPrice().compareTo(BigDecimal.ZERO) > 0) { + throw exception(SALE_RETURN_PROCESS_FAIL_EXISTS_REFUND); + } + + // 2. 更新状态 + int updateCount = saleReturnMapper.updateByIdAndStatus(id, saleReturn.getStatus(), + new ErpSaleReturnDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? SALE_RETURN_APPROVE_FAIL : SALE_RETURN_PROCESS_FAIL); + } + + // 3. 变更库存 + List saleReturnItems = saleReturnItemMapper.selectListByReturnId(id); + Integer bizType = approve ? ErpStockRecordBizTypeEnum.SALE_RETURN.getType() + : ErpStockRecordBizTypeEnum.SALE_RETURN_CANCEL.getType(); + saleReturnItems.forEach(saleReturnItem -> { + BigDecimal count = approve ? saleReturnItem.getCount() : saleReturnItem.getCount().negate(); + stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( + saleReturnItem.getProductId(), saleReturnItem.getWarehouseId(), count, + bizType, saleReturnItem.getReturnId(), saleReturnItem.getId(), saleReturn.getNo())); + }); + } + + @Override + public void updateSaleReturnRefundPrice(Long id, BigDecimal refundPrice) { + ErpSaleReturnDO saleReturn = saleReturnMapper.selectById(id); + if (saleReturn.getRefundPrice().equals(refundPrice)) { + return; + } + if (refundPrice.compareTo(saleReturn.getTotalPrice()) > 0) { + throw exception(SALE_RETURN_FAIL_REFUND_PRICE_EXCEED, refundPrice, saleReturn.getTotalPrice()); + } + saleReturnMapper.updateById(new ErpSaleReturnDO().setId(id).setRefundPrice(refundPrice)); + } + + private List validateSaleReturnItems(List list) { + // 1. 校验产品存在 + List productList = productService.validProductList( + convertSet(list, ErpSaleReturnSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + // 2. 转化为 ErpSaleReturnItemDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, ErpSaleReturnItemDO.class, item -> { + item.setProductUnitId(productMap.get(item.getProductId()).getUnitId()); + item.setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())); + if (item.getTotalPrice() == null) { + return; + } + if (item.getTaxPercent() != null) { + item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent())); + } + })); + } + + private void updateSaleReturnItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = saleReturnItemMapper.selectListByReturnId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setReturnId(id)); + saleReturnItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + saleReturnItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + saleReturnItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpSaleReturnItemDO::getId)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteSaleReturn(List ids) { + // 1. 校验不处于已审批 + List saleReturns = saleReturnMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(saleReturns)) { + return; + } + saleReturns.forEach(saleReturn -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(saleReturn.getStatus())) { + throw exception(SALE_RETURN_DELETE_FAIL_APPROVE, saleReturn.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + saleReturns.forEach(saleReturn -> { + // 2.1 删除订单 + saleReturnMapper.deleteById(saleReturn.getId()); + // 2.2 删除订单项 + saleReturnItemMapper.deleteByReturnId(saleReturn.getId()); + + // 2.3 更新销售订单的出库数量 + updateSaleOrderReturnCount(saleReturn.getOrderId()); + }); + + } + + private ErpSaleReturnDO validateSaleReturnExists(Long id) { + ErpSaleReturnDO saleReturn = saleReturnMapper.selectById(id); + if (saleReturn == null) { + throw exception(SALE_RETURN_NOT_EXISTS); + } + return saleReturn; + } + + @Override + public ErpSaleReturnDO getSaleReturn(Long id) { + return saleReturnMapper.selectById(id); + } + + @Override + public ErpSaleReturnDO validateSaleReturn(Long id) { + ErpSaleReturnDO saleReturn = validateSaleReturnExists(id); + if (ObjectUtil.notEqual(saleReturn.getStatus(), ErpAuditStatus.APPROVE.getStatus())) { + throw exception(SALE_RETURN_NOT_APPROVE); + } + return saleReturn; + } + + @Override + public PageResult getSaleReturnPage(ErpSaleReturnPageReqVO pageReqVO) { + return saleReturnMapper.selectPage(pageReqVO); + } + + // ==================== 销售退货项 ==================== + + @Override + public List getSaleReturnItemListByReturnId(Long returnId) { + return saleReturnItemMapper.selectListByReturnId(returnId); + } + + @Override + public List getSaleReturnItemListByReturnIds(Collection returnIds) { + if (CollUtil.isEmpty(returnIds)) { + return Collections.emptyList(); + } + return saleReturnItemMapper.selectListByReturnIds(returnIds); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckService.java new file mode 100644 index 000000000..02a192165 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckService.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckItemDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * ERP 库存盘点单 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpStockCheckService { + + /** + * 创建库存盘点单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createStockCheck(@Valid ErpStockCheckSaveReqVO createReqVO); + + /** + * 更新库存盘点单 + * + * @param updateReqVO 更新信息 + */ + void updateStockCheck(@Valid ErpStockCheckSaveReqVO updateReqVO); + + /** + * 更新库存盘点单的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updateStockCheckStatus(Long id, Integer status); + + /** + * 删除库存盘点单 + * + * @param ids 编号数组 + */ + void deleteStockCheck(List ids); + + /** + * 获得库存盘点单 + * + * @param id 编号 + * @return 库存盘点单 + */ + ErpStockCheckDO getStockCheck(Long id); + + /** + * 获得库存盘点单分页 + * + * @param pageReqVO 分页查询 + * @return 库存盘点单分页 + */ + PageResult getStockCheckPage(ErpStockCheckPageReqVO pageReqVO); + + // ==================== 盘点项 ==================== + + /** + * 获得库存盘点单项列表 + * + * @param checkId 盘点编号 + * @return 库存盘点单项列表 + */ + List getStockCheckItemListByCheckId(Long checkId); + + /** + * 获得库存盘点单项 List + * + * @param checkIds 盘点编号数组 + * @return 库存盘点单项 List + */ + List getStockCheckItemListByCheckIds(Collection checkIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckServiceImpl.java new file mode 100644 index 000000000..16afc71be --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckServiceImpl.java @@ -0,0 +1,232 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockCheckItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockCheckMapper; +import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 库存盘点单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpStockCheckServiceImpl implements ErpStockCheckService { + + @Resource + private ErpStockCheckMapper stockCheckMapper; + @Resource + private ErpStockCheckItemMapper stockCheckItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpProductService productService; + @Resource + private ErpWarehouseService warehouseService; + @Resource + private ErpStockRecordService stockRecordService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createStockCheck(ErpStockCheckSaveReqVO createReqVO) { + // 1.1 校验盘点项的有效性 + List stockCheckItems = validateStockCheckItems(createReqVO.getItems()); + // 1.2 生成盘点单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_CHECK_NO_PREFIX); + if (stockCheckMapper.selectByNo(no) != null) { + throw exception(STOCK_CHECK_NO_EXISTS); + } + + // 2.1 插入盘点单 + ErpStockCheckDO stockCheck = BeanUtils.toBean(createReqVO, ErpStockCheckDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus()) + .setTotalCount(getSumValue(stockCheckItems, ErpStockCheckItemDO::getCount, BigDecimal::add)) + .setTotalPrice(getSumValue(stockCheckItems, ErpStockCheckItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); + stockCheckMapper.insert(stockCheck); + // 2.2 插入盘点单项 + stockCheckItems.forEach(o -> o.setCheckId(stockCheck.getId())); + stockCheckItemMapper.insertBatch(stockCheckItems); + return stockCheck.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStockCheck(ErpStockCheckSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpStockCheckDO stockCheck = validateStockCheckExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(stockCheck.getStatus())) { + throw exception(STOCK_CHECK_UPDATE_FAIL_APPROVE, stockCheck.getNo()); + } + // 1.2 校验盘点项的有效性 + List stockCheckItems = validateStockCheckItems(updateReqVO.getItems()); + + // 2.1 更新盘点单 + ErpStockCheckDO updateObj = BeanUtils.toBean(updateReqVO, ErpStockCheckDO.class, in -> in + .setTotalCount(getSumValue(stockCheckItems, ErpStockCheckItemDO::getCount, BigDecimal::add)) + .setTotalPrice(getSumValue(stockCheckItems, ErpStockCheckItemDO::getTotalPrice, BigDecimal::add))); + stockCheckMapper.updateById(updateObj); + // 2.2 更新盘点单项 + updateStockCheckItemList(updateReqVO.getId(), stockCheckItems); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStockCheckStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpStockCheckDO stockCheck = validateStockCheckExists(id); + // 1.2 校验状态 + if (stockCheck.getStatus().equals(status)) { + throw exception(approve ? STOCK_CHECK_APPROVE_FAIL : STOCK_CHECK_PROCESS_FAIL); + } + + // 2. 更新状态 + int updateCount = stockCheckMapper.updateByIdAndStatus(id, stockCheck.getStatus(), + new ErpStockCheckDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? STOCK_CHECK_APPROVE_FAIL : STOCK_CHECK_PROCESS_FAIL); + } + + // 3. 变更库存 + List stockCheckItems = stockCheckItemMapper.selectListByCheckId(id); + stockCheckItems.forEach(stockCheckItem -> { + // 没有盈亏,不用出入库 + if (stockCheckItem.getCount().compareTo(BigDecimal.ZERO) == 0) { + return; + } + // 10;12;-2() + BigDecimal count = approve ? stockCheckItem.getCount(): stockCheckItem.getCount().negate(); + Integer bizType; + if (approve) { + bizType = count.compareTo(BigDecimal.ZERO) > 0 ? ErpStockRecordBizTypeEnum.CHECK_MORE_IN.getType() + : ErpStockRecordBizTypeEnum.CHECK_LESS_OUT.getType(); + } else { + bizType = count.compareTo(BigDecimal.ZERO) > 0 ? ErpStockRecordBizTypeEnum.CHECK_MORE_IN_CANCEL.getType() + : ErpStockRecordBizTypeEnum.CHECK_LESS_OUT_CANCEL.getType(); + } + stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( + stockCheckItem.getProductId(), stockCheckItem.getWarehouseId(), count, + bizType, stockCheckItem.getCheckId(), stockCheckItem.getId(), stockCheck.getNo())); + }); + } + + private List validateStockCheckItems(List list) { + // 1.1 校验产品存在 + List productList = productService.validProductList( + convertSet(list, ErpStockCheckSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + // 1.2 校验仓库存在 + warehouseService.validWarehouseList(convertSet(list, ErpStockCheckSaveReqVO.Item::getWarehouseId)); + // 2. 转化为 ErpStockCheckItemDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, ErpStockCheckItemDO.class, item -> item + .setProductUnitId(productMap.get(item.getProductId()).getUnitId()) + .setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())))); + } + + private void updateStockCheckItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = stockCheckItemMapper.selectListByCheckId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setCheckId(id)); + stockCheckItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + stockCheckItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + stockCheckItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpStockCheckItemDO::getId)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStockCheck(List ids) { + // 1. 校验不处于已审批 + List stockChecks = stockCheckMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(stockChecks)) { + return; + } + stockChecks.forEach(stockCheck -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(stockCheck.getStatus())) { + throw exception(STOCK_CHECK_DELETE_FAIL_APPROVE, stockCheck.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + stockChecks.forEach(stockCheck -> { + // 2.1 删除盘点单 + stockCheckMapper.deleteById(stockCheck.getId()); + // 2.2 删除盘点单项 + stockCheckItemMapper.deleteByCheckId(stockCheck.getId()); + }); + } + + private ErpStockCheckDO validateStockCheckExists(Long id) { + ErpStockCheckDO stockCheck = stockCheckMapper.selectById(id); + if (stockCheck == null) { + throw exception(STOCK_CHECK_NOT_EXISTS); + } + return stockCheck; + } + + @Override + public ErpStockCheckDO getStockCheck(Long id) { + return stockCheckMapper.selectById(id); + } + + @Override + public PageResult getStockCheckPage(ErpStockCheckPageReqVO pageReqVO) { + return stockCheckMapper.selectPage(pageReqVO); + } + + // ==================== 盘点项 ==================== + + @Override + public List getStockCheckItemListByCheckId(Long checkId) { + return stockCheckItemMapper.selectListByCheckId(checkId); + } + + @Override + public List getStockCheckItemListByCheckIds(Collection checkIds) { + if (CollUtil.isEmpty(checkIds)) { + return Collections.emptyList(); + } + return stockCheckItemMapper.selectListByCheckIds(checkIds); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInService.java new file mode 100644 index 000000000..65a5063e8 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInService.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * ERP 其它入库单 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpStockInService { + + /** + * 创建其它入库单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createStockIn(@Valid ErpStockInSaveReqVO createReqVO); + + /** + * 更新其它入库单 + * + * @param updateReqVO 更新信息 + */ + void updateStockIn(@Valid ErpStockInSaveReqVO updateReqVO); + + /** + * 更新其它入库单的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updateStockInStatus(Long id, Integer status); + + /** + * 删除其它入库单 + * + * @param ids 编号数组 + */ + void deleteStockIn(List ids); + + /** + * 获得其它入库单 + * + * @param id 编号 + * @return 其它入库单 + */ + ErpStockInDO getStockIn(Long id); + + /** + * 获得其它入库单分页 + * + * @param pageReqVO 分页查询 + * @return 其它入库单分页 + */ + PageResult getStockInPage(ErpStockInPageReqVO pageReqVO); + + // ==================== 入库项 ==================== + + /** + * 获得其它入库单项列表 + * + * @param inId 入库编号 + * @return 其它入库单项列表 + */ + List getStockInItemListByInId(Long inId); + + /** + * 获得其它入库单项 List + * + * @param inIds 入库编号数组 + * @return 其它入库单项 List + */ + List getStockInItemListByInIds(Collection inIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java new file mode 100644 index 000000000..85d93d881 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java @@ -0,0 +1,228 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInMapper; +import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 +/** + * ERP 其它入库单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpStockInServiceImpl implements ErpStockInService { + + @Resource + private ErpStockInMapper stockInMapper; + @Resource + private ErpStockInItemMapper stockInItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpProductService productService; + @Resource + private ErpWarehouseService warehouseService; + @Resource + private ErpSupplierService supplierService; + @Resource + private ErpStockRecordService stockRecordService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createStockIn(ErpStockInSaveReqVO createReqVO) { + // 1.1 校验入库项的有效性 + List stockInItems = validateStockInItems(createReqVO.getItems()); + // 1.2 校验供应商 + supplierService.validateSupplier(createReqVO.getSupplierId()); + // 1.3 生成入库单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_IN_NO_PREFIX); + if (stockInMapper.selectByNo(no) != null) { + throw exception(STOCK_IN_NO_EXISTS); + } + + // 2.1 插入入库单 + ErpStockInDO stockIn = BeanUtils.toBean(createReqVO, ErpStockInDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus()) + .setTotalCount(getSumValue(stockInItems, ErpStockInItemDO::getCount, BigDecimal::add)) + .setTotalPrice(getSumValue(stockInItems, ErpStockInItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); + stockInMapper.insert(stockIn); + // 2.2 插入入库单项 + stockInItems.forEach(o -> o.setInId(stockIn.getId())); + stockInItemMapper.insertBatch(stockInItems); + return stockIn.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStockIn(ErpStockInSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpStockInDO stockIn = validateStockInExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(stockIn.getStatus())) { + throw exception(STOCK_IN_UPDATE_FAIL_APPROVE, stockIn.getNo()); + } + // 1.2 校验供应商 + supplierService.validateSupplier(updateReqVO.getSupplierId()); + // 1.3 校验入库项的有效性 + List stockInItems = validateStockInItems(updateReqVO.getItems()); + + // 2.1 更新入库单 + ErpStockInDO updateObj = BeanUtils.toBean(updateReqVO, ErpStockInDO.class, in -> in + .setTotalCount(getSumValue(stockInItems, ErpStockInItemDO::getCount, BigDecimal::add)) + .setTotalPrice(getSumValue(stockInItems, ErpStockInItemDO::getTotalPrice, BigDecimal::add))); + stockInMapper.updateById(updateObj); + // 2.2 更新入库单项 + updateStockInItemList(updateReqVO.getId(), stockInItems); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStockInStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpStockInDO stockIn = validateStockInExists(id); + // 1.2 校验状态 + if (stockIn.getStatus().equals(status)) { + throw exception(approve ? STOCK_IN_APPROVE_FAIL : STOCK_IN_PROCESS_FAIL); + } + + // 2. 更新状态 + int updateCount = stockInMapper.updateByIdAndStatus(id, stockIn.getStatus(), + new ErpStockInDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? STOCK_IN_APPROVE_FAIL : STOCK_IN_PROCESS_FAIL); + } + + // 3. 变更库存 + List stockInItems = stockInItemMapper.selectListByInId(id); + Integer bizType = approve ? ErpStockRecordBizTypeEnum.OTHER_IN.getType() + : ErpStockRecordBizTypeEnum.OTHER_IN_CANCEL.getType(); + stockInItems.forEach(stockInItem -> { + BigDecimal count = approve ? stockInItem.getCount() : stockInItem.getCount().negate(); + stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( + stockInItem.getProductId(), stockInItem.getWarehouseId(), count, + bizType, stockInItem.getInId(), stockInItem.getId(), stockIn.getNo())); + }); + } + + private List validateStockInItems(List list) { + // 1.1 校验产品存在 + List productList = productService.validProductList( + convertSet(list, ErpStockInSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + // 1.2 校验仓库存在 + warehouseService.validWarehouseList(convertSet( + list, ErpStockInSaveReqVO.Item::getWarehouseId)); + // 2. 转化为 ErpStockInItemDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, ErpStockInItemDO.class, item -> item + .setProductUnitId(productMap.get(item.getProductId()).getUnitId()) + .setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())))); + } + + private void updateStockInItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = stockInItemMapper.selectListByInId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setInId(id)); + stockInItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + stockInItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + stockInItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpStockInItemDO::getId)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStockIn(List ids) { + // 1. 校验不处于已审批 + List stockIns = stockInMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(stockIns)) { + return; + } + stockIns.forEach(stockIn -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(stockIn.getStatus())) { + throw exception(STOCK_IN_DELETE_FAIL_APPROVE, stockIn.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + stockIns.forEach(stockIn -> { + // 2.1 删除入库单 + stockInMapper.deleteById(stockIn.getId()); + // 2.2 删除入库单项 + stockInItemMapper.deleteByInId(stockIn.getId()); + }); + } + + private ErpStockInDO validateStockInExists(Long id) { + ErpStockInDO stockIn = stockInMapper.selectById(id); + if (stockIn == null) { + throw exception(STOCK_IN_NOT_EXISTS); + } + return stockIn; + } + + @Override + public ErpStockInDO getStockIn(Long id) { + return stockInMapper.selectById(id); + } + + @Override + public PageResult getStockInPage(ErpStockInPageReqVO pageReqVO) { + return stockInMapper.selectPage(pageReqVO); + } + + // ==================== 入库项 ==================== + + @Override + public List getStockInItemListByInId(Long inId) { + return stockInItemMapper.selectListByInId(inId); + } + + @Override + public List getStockInItemListByInIds(Collection inIds) { + if (CollUtil.isEmpty(inIds)) { + return Collections.emptyList(); + } + return stockInItemMapper.selectListByInIds(inIds); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveService.java new file mode 100644 index 000000000..b7d4ecf86 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveService.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMovePageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveItemDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * ERP 库存调拨单 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpStockMoveService { + + /** + * 创建库存调拨单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createStockMove(@Valid ErpStockMoveSaveReqVO createReqVO); + + /** + * 更新库存调拨单 + * + * @param updateReqVO 更新信息 + */ + void updateStockMove(@Valid ErpStockMoveSaveReqVO updateReqVO); + + /** + * 更新库存调拨单的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updateStockMoveStatus(Long id, Integer status); + + /** + * 删除库存调拨单 + * + * @param ids 编号数组 + */ + void deleteStockMove(List ids); + + /** + * 获得库存调拨单 + * + * @param id 编号 + * @return 库存调拨单 + */ + ErpStockMoveDO getStockMove(Long id); + + /** + * 获得库存调拨单分页 + * + * @param pageReqVO 分页查询 + * @return 库存调拨单分页 + */ + PageResult getStockMovePage(ErpStockMovePageReqVO pageReqVO); + + // ==================== 调拨项 ==================== + + /** + * 获得库存调拨单项列表 + * + * @param moveId 调拨编号 + * @return 库存调拨单项列表 + */ + List getStockMoveItemListByMoveId(Long moveId); + + /** + * 获得库存调拨单项 List + * + * @param moveIds 调拨编号数组 + * @return 库存调拨单项 List + */ + List getStockMoveItemListByMoveIds(Collection moveIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveServiceImpl.java new file mode 100644 index 000000000..d99d02618 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveServiceImpl.java @@ -0,0 +1,229 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMovePageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockMoveItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockMoveMapper; +import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 库存调拨单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpStockMoveServiceImpl implements ErpStockMoveService { + + @Resource + private ErpStockMoveMapper stockMoveMapper; + @Resource + private ErpStockMoveItemMapper stockMoveItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpProductService productService; + @Resource + private ErpWarehouseService warehouseService; + @Resource + private ErpStockRecordService stockRecordService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createStockMove(ErpStockMoveSaveReqVO createReqVO) { + // 1.1 校验出库项的有效性 + List stockMoveItems = validateStockMoveItems(createReqVO.getItems()); + // 1.2 生成调拨单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_MOVE_NO_PREFIX); + if (stockMoveMapper.selectByNo(no) != null) { + throw exception(STOCK_MOVE_NO_EXISTS); + } + + // 2.1 插入出库单 + ErpStockMoveDO stockMove = BeanUtils.toBean(createReqVO, ErpStockMoveDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus()) + .setTotalCount(getSumValue(stockMoveItems, ErpStockMoveItemDO::getCount, BigDecimal::add)) + .setTotalPrice(getSumValue(stockMoveItems, ErpStockMoveItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); + stockMoveMapper.insert(stockMove); + // 2.2 插入出库单项 + stockMoveItems.forEach(o -> o.setMoveId(stockMove.getId())); + stockMoveItemMapper.insertBatch(stockMoveItems); + return stockMove.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStockMove(ErpStockMoveSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpStockMoveDO stockMove = validateStockMoveExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(stockMove.getStatus())) { + throw exception(STOCK_MOVE_UPDATE_FAIL_APPROVE, stockMove.getNo()); + } + // 1.2 校验出库项的有效性 + List stockMoveItems = validateStockMoveItems(updateReqVO.getItems()); + + // 2.1 更新出库单 + ErpStockMoveDO updateObj = BeanUtils.toBean(updateReqVO, ErpStockMoveDO.class, in -> in + .setTotalCount(getSumValue(stockMoveItems, ErpStockMoveItemDO::getCount, BigDecimal::add)) + .setTotalPrice(getSumValue(stockMoveItems, ErpStockMoveItemDO::getTotalPrice, BigDecimal::add))); + stockMoveMapper.updateById(updateObj); + // 2.2 更新出库单项 + updateStockMoveItemList(updateReqVO.getId(), stockMoveItems); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStockMoveStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpStockMoveDO stockMove = validateStockMoveExists(id); + // 1.2 校验状态 + if (stockMove.getStatus().equals(status)) { + throw exception(approve ? STOCK_MOVE_APPROVE_FAIL : STOCK_MOVE_PROCESS_FAIL); + } + + // 2. 更新状态 + int updateCount = stockMoveMapper.updateByIdAndStatus(id, stockMove.getStatus(), + new ErpStockMoveDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? STOCK_MOVE_APPROVE_FAIL : STOCK_MOVE_PROCESS_FAIL); + } + + // 3. 变更库存 + List stockMoveItems = stockMoveItemMapper.selectListByMoveId(id); + Integer fromBizType = approve ? ErpStockRecordBizTypeEnum.MOVE_OUT.getType() + : ErpStockRecordBizTypeEnum.MOVE_OUT_CANCEL.getType(); + Integer toBizType = approve ? ErpStockRecordBizTypeEnum.MOVE_IN.getType() + : ErpStockRecordBizTypeEnum.MOVE_IN_CANCEL.getType(); + stockMoveItems.forEach(stockMoveItem -> { + BigDecimal fromCount = approve ? stockMoveItem.getCount().negate() : stockMoveItem.getCount(); + BigDecimal toCount = approve ? stockMoveItem.getCount() : stockMoveItem.getCount().negate(); + stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( + stockMoveItem.getProductId(), stockMoveItem.getFromWarehouseId(), fromCount, + fromBizType, stockMoveItem.getMoveId(), stockMoveItem.getId(), stockMove.getNo())); + stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( + stockMoveItem.getProductId(), stockMoveItem.getToWarehouseId(), toCount, + toBizType, stockMoveItem.getMoveId(), stockMoveItem.getId(), stockMove.getNo())); + }); + } + + private List validateStockMoveItems(List list) { + // 1.1 校验产品存在 + List productList = productService.validProductList( + convertSet(list, ErpStockMoveSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + // 1.2 校验仓库存在 + warehouseService.validWarehouseList(convertSetByFlatMap(list, + item -> Stream.of(item.getFromWarehouseId(), item.getToWarehouseId()))); + // 2. 转化为 ErpStockMoveItemDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, ErpStockMoveItemDO.class, item -> item + .setProductUnitId(productMap.get(item.getProductId()).getUnitId()) + .setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())))); + } + + private void updateStockMoveItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = stockMoveItemMapper.selectListByMoveId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setMoveId(id)); + stockMoveItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + stockMoveItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + stockMoveItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpStockMoveItemDO::getId)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStockMove(List ids) { + // 1. 校验不处于已审批 + List stockMoves = stockMoveMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(stockMoves)) { + return; + } + stockMoves.forEach(stockMove -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(stockMove.getStatus())) { + throw exception(STOCK_MOVE_DELETE_FAIL_APPROVE, stockMove.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + stockMoves.forEach(stockMove -> { + // 2.1 删除出库单 + stockMoveMapper.deleteById(stockMove.getId()); + // 2.2 删除出库单项 + stockMoveItemMapper.deleteByMoveId(stockMove.getId()); + }); + } + + private ErpStockMoveDO validateStockMoveExists(Long id) { + ErpStockMoveDO stockMove = stockMoveMapper.selectById(id); + if (stockMove == null) { + throw exception(STOCK_MOVE_NOT_EXISTS); + } + return stockMove; + } + + @Override + public ErpStockMoveDO getStockMove(Long id) { + return stockMoveMapper.selectById(id); + } + + @Override + public PageResult getStockMovePage(ErpStockMovePageReqVO pageReqVO) { + return stockMoveMapper.selectPage(pageReqVO); + } + + // ==================== 出库项 ==================== + + @Override + public List getStockMoveItemListByMoveId(Long moveId) { + return stockMoveItemMapper.selectListByMoveId(moveId); + } + + @Override + public List getStockMoveItemListByMoveIds(Collection moveIds) { + if (CollUtil.isEmpty(moveIds)) { + return Collections.emptyList(); + } + return stockMoveItemMapper.selectListByMoveIds(moveIds); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutService.java new file mode 100644 index 000000000..ffd17fca1 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutService.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * ERP 其它出库单 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpStockOutService { + + /** + * 创建其它出库单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createStockOut(@Valid ErpStockOutSaveReqVO createReqVO); + + /** + * 更新其它出库单 + * + * @param updateReqVO 更新信息 + */ + void updateStockOut(@Valid ErpStockOutSaveReqVO updateReqVO); + + /** + * 更新其它出库单的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updateStockOutStatus(Long id, Integer status); + + /** + * 删除其它出库单 + * + * @param ids 编号数组 + */ + void deleteStockOut(List ids); + + /** + * 获得其它出库单 + * + * @param id 编号 + * @return 其它出库单 + */ + ErpStockOutDO getStockOut(Long id); + + /** + * 获得其它出库单分页 + * + * @param pageReqVO 分页查询 + * @return 其它出库单分页 + */ + PageResult getStockOutPage(ErpStockOutPageReqVO pageReqVO); + + // ==================== 出库项 ==================== + + /** + * 获得其它出库单项列表 + * + * @param outId 出库编号 + * @return 其它出库单项列表 + */ + List getStockOutItemListByOutId(Long outId); + + /** + * 获得其它出库单项 List + * + * @param outIds 出库编号数组 + * @return 其它出库单项 List + */ + List getStockOutItemListByOutIds(Collection outIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java new file mode 100644 index 000000000..aa7428c17 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java @@ -0,0 +1,228 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutMapper; +import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 其它出库单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpStockOutServiceImpl implements ErpStockOutService { + + @Resource + private ErpStockOutMapper stockOutMapper; + @Resource + private ErpStockOutItemMapper stockOutItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpProductService productService; + @Resource + private ErpWarehouseService warehouseService; + @Resource + private ErpCustomerService customerService; + @Resource + private ErpStockRecordService stockRecordService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createStockOut(ErpStockOutSaveReqVO createReqVO) { + // 1.1 校验出库项的有效性 + List stockOutItems = validateStockOutItems(createReqVO.getItems()); + // 1.2 校验客户 + customerService.validateCustomer(createReqVO.getCustomerId()); + // 1.3 生成出库单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_OUT_NO_PREFIX); + if (stockOutMapper.selectByNo(no) != null) { + throw exception(STOCK_OUT_NO_EXISTS); + } + + // 2.1 插入出库单 + ErpStockOutDO stockOut = BeanUtils.toBean(createReqVO, ErpStockOutDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus()) + .setTotalCount(getSumValue(stockOutItems, ErpStockOutItemDO::getCount, BigDecimal::add)) + .setTotalPrice(getSumValue(stockOutItems, ErpStockOutItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); + stockOutMapper.insert(stockOut); + // 2.2 插入出库单项 + stockOutItems.forEach(o -> o.setOutId(stockOut.getId())); + stockOutItemMapper.insertBatch(stockOutItems); + return stockOut.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStockOut(ErpStockOutSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpStockOutDO stockOut = validateStockOutExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(stockOut.getStatus())) { + throw exception(STOCK_OUT_UPDATE_FAIL_APPROVE, stockOut.getNo()); + } + // 1.2 校验客户 + customerService.validateCustomer(updateReqVO.getCustomerId()); + // 1.3 校验出库项的有效性 + List stockOutItems = validateStockOutItems(updateReqVO.getItems()); + + // 2.1 更新出库单 + ErpStockOutDO updateObj = BeanUtils.toBean(updateReqVO, ErpStockOutDO.class, in -> in + .setTotalCount(getSumValue(stockOutItems, ErpStockOutItemDO::getCount, BigDecimal::add)) + .setTotalPrice(getSumValue(stockOutItems, ErpStockOutItemDO::getTotalPrice, BigDecimal::add))); + stockOutMapper.updateById(updateObj); + // 2.2 更新出库单项 + updateStockOutItemList(updateReqVO.getId(), stockOutItems); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStockOutStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpStockOutDO stockOut = validateStockOutExists(id); + // 1.2 校验状态 + if (stockOut.getStatus().equals(status)) { + throw exception(approve ? STOCK_OUT_APPROVE_FAIL : STOCK_OUT_PROCESS_FAIL); + } + + // 2. 更新状态 + int updateCount = stockOutMapper.updateByIdAndStatus(id, stockOut.getStatus(), + new ErpStockOutDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? STOCK_OUT_APPROVE_FAIL : STOCK_OUT_PROCESS_FAIL); + } + + // 3. 变更库存 + List stockOutItems = stockOutItemMapper.selectListByOutId(id); + Integer bizType = approve ? ErpStockRecordBizTypeEnum.OTHER_OUT.getType() + : ErpStockRecordBizTypeEnum.OTHER_OUT_CANCEL.getType(); + stockOutItems.forEach(stockOutItem -> { + BigDecimal count = approve ? stockOutItem.getCount().negate() : stockOutItem.getCount(); + stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( + stockOutItem.getProductId(), stockOutItem.getWarehouseId(), count, + bizType, stockOutItem.getOutId(), stockOutItem.getId(), stockOut.getNo())); + }); + } + + private List validateStockOutItems(List list) { + // 1.1 校验产品存在 + List productList = productService.validProductList( + convertSet(list, ErpStockOutSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + // 1.2 校验仓库存在 + warehouseService.validWarehouseList(convertSet(list, ErpStockOutSaveReqVO.Item::getWarehouseId)); + // 2. 转化为 ErpStockOutItemDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, ErpStockOutItemDO.class, item -> item + .setProductUnitId(productMap.get(item.getProductId()).getUnitId()) + .setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())))); + } + + private void updateStockOutItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = stockOutItemMapper.selectListByOutId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setOutId(id)); + stockOutItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + stockOutItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + stockOutItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpStockOutItemDO::getId)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStockOut(List ids) { + // 1. 校验不处于已审批 + List stockOuts = stockOutMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(stockOuts)) { + return; + } + stockOuts.forEach(stockOut -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(stockOut.getStatus())) { + throw exception(STOCK_OUT_DELETE_FAIL_APPROVE, stockOut.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + stockOuts.forEach(stockOut -> { + // 2.1 删除出库单 + stockOutMapper.deleteById(stockOut.getId()); + // 2.2 删除出库单项 + stockOutItemMapper.deleteByOutId(stockOut.getId()); + }); + } + + private ErpStockOutDO validateStockOutExists(Long id) { + ErpStockOutDO stockOut = stockOutMapper.selectById(id); + if (stockOut == null) { + throw exception(STOCK_OUT_NOT_EXISTS); + } + return stockOut; + } + + @Override + public ErpStockOutDO getStockOut(Long id) { + return stockOutMapper.selectById(id); + } + + @Override + public PageResult getStockOutPage(ErpStockOutPageReqVO pageReqVO) { + return stockOutMapper.selectPage(pageReqVO); + } + + // ==================== 出库项 ==================== + + @Override + public List getStockOutItemListByOutId(Long outId) { + return stockOutItemMapper.selectListByOutId(outId); + } + + @Override + public List getStockOutItemListByOutIds(Collection outIds) { + if (CollUtil.isEmpty(outIds)) { + return Collections.emptyList(); + } + return stockOutItemMapper.selectListByOutIds(outIds); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java new file mode 100644 index 000000000..aa9072e81 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record.ErpStockRecordPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; + +import javax.validation.Valid; + +/** + * ERP 产品库存明细 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpStockRecordService { + + /** + * 获得产品库存明细 + * + * @param id 编号 + * @return 产品库存明细 + */ + ErpStockRecordDO getStockRecord(Long id); + + /** + * 获得产品库存明细分页 + * + * @param pageReqVO 分页查询 + * @return 产品库存明细分页 + */ + PageResult getStockRecordPage(ErpStockRecordPageReqVO pageReqVO); + + /** + * 创建库存明细 + * + * @param createReqBO 创建库存明细 BO + */ + void createStockRecord(@Valid ErpStockRecordCreateReqBO createReqBO); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java new file mode 100644 index 000000000..b4b3875da --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record.ErpStockRecordPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockRecordMapper; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.math.BigDecimal; + +/** + * ERP 产品库存明细 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpStockRecordServiceImpl implements ErpStockRecordService { + + @Resource + private ErpStockRecordMapper stockRecordMapper; + + @Resource + private ErpStockService stockService; + + @Override + public ErpStockRecordDO getStockRecord(Long id) { + return stockRecordMapper.selectById(id); + } + + @Override + public PageResult getStockRecordPage(ErpStockRecordPageReqVO pageReqVO) { + return stockRecordMapper.selectPage(pageReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void createStockRecord(ErpStockRecordCreateReqBO createReqBO) { + // 1. 更新库存 + BigDecimal totalCount = stockService.updateStockCountIncrement( + createReqBO.getProductId(), createReqBO.getWarehouseId(), createReqBO.getCount()); + // 2. 创建库存明细 + ErpStockRecordDO stockRecord = BeanUtils.toBean(createReqBO, ErpStockRecordDO.class) + .setTotalCount(totalCount); + stockRecordMapper.insert(stockRecord); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java new file mode 100644 index 000000000..63ad5fefa --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; + +import java.math.BigDecimal; + +/** + * ERP 产品库存 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpStockService { + + /** + * 获得产品库存 + * + * @param id 编号 + * @return 库存 + */ + ErpStockDO getStock(Long id); + + /** + * 基于产品 + 仓库,获得产品库存 + * + * @param productId 产品编号 + * @param warehouseId 仓库编号 + * @return 产品库存 + */ + ErpStockDO getStock(Long productId, Long warehouseId); + + /** + * 获得产品库存数量 + * + * 如果不存在库存记录,则返回 0 + * + * @param productId 产品编号 + * @return 产品库存数量 + */ + BigDecimal getStockCount(Long productId); + + /** + * 获得产品库存分页 + * + * @param pageReqVO 分页查询 + * @return 库存分页 + */ + PageResult getStockPage(ErpStockPageReqVO pageReqVO); + + /** + * 增量更新产品库存数量 + * + * @param productId 产品编号 + * @param warehouseId 仓库编号 + * @param count 增量数量:正数,表示增加;负数,表示减少 + * @return 更新后的库存 + */ + BigDecimal updateStockCountIncrement(Long productId, Long warehouseId, BigDecimal count); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java new file mode 100644 index 000000000..dabe36fb9 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java @@ -0,0 +1,89 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockMapper; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.math.BigDecimal; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_COUNT_NEGATIVE; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_COUNT_NEGATIVE2; + +/** + * ERP 产品库存 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpStockServiceImpl implements ErpStockService { + + /** + * 允许库存为负数 + * + * TODO 芋艿:后续做成 db 配置 + */ + private static final Boolean NEGATIVE_STOCK_COUNT_ENABLE = false; + + @Resource + private ErpProductService productService; + @Resource + private ErpWarehouseService warehouseService; + + @Resource + private ErpStockMapper stockMapper; + + @Override + public ErpStockDO getStock(Long id) { + return stockMapper.selectById(id); + } + + @Override + public ErpStockDO getStock(Long productId, Long warehouseId) { + return stockMapper.selectByProductIdAndWarehouseId(productId, warehouseId); + } + + @Override + public BigDecimal getStockCount(Long productId) { + BigDecimal count = stockMapper.selectSumByProductId(productId); + return count != null ? count : BigDecimal.ZERO; + } + + @Override + public PageResult getStockPage(ErpStockPageReqVO pageReqVO) { + return stockMapper.selectPage(pageReqVO); + } + + @Override + public BigDecimal updateStockCountIncrement(Long productId, Long warehouseId, BigDecimal count) { + // 1.1 查询当前库存 + ErpStockDO stock = stockMapper.selectByProductIdAndWarehouseId(productId, warehouseId); + if (stock == null) { + stock = new ErpStockDO().setProductId(productId).setWarehouseId(warehouseId).setCount(BigDecimal.ZERO); + stockMapper.insert(stock); + } + // 1.2 校验库存是否充足 + if (!NEGATIVE_STOCK_COUNT_ENABLE && stock.getCount().add(count).compareTo(BigDecimal.ZERO) < 0) { + throw exception(STOCK_COUNT_NEGATIVE, productService.getProduct(productId).getName(), + warehouseService.getWarehouse(warehouseId).getName(), stock.getCount(), count); + } + + // 2. 库存变更 + int updateCount = stockMapper.updateCountIncrement(stock.getId(), count, NEGATIVE_STOCK_COUNT_ENABLE); + if (updateCount == 0) { + // 此时不好去查询最新库存,所以直接抛出该提示,不提供具体库存数字 + throw exception(STOCK_COUNT_NEGATIVE2, productService.getProduct(productId).getName(), + warehouseService.getWarehouse(warehouseId).getName()); + } + + // 3. 返回最新库存 + return stock.getCount().add(count); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java new file mode 100644 index 000000000..01e8df682 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.ErpWarehouseSaveReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehousePageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * ERP 仓库 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpWarehouseService { + + /** + * 创建仓库 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createWarehouse(@Valid ErpWarehouseSaveReqVO createReqVO); + + /** + * 更新ERP 仓库 + * + * @param updateReqVO 更新信息 + */ + void updateWarehouse(@Valid ErpWarehouseSaveReqVO updateReqVO); + + /** + * 更新仓库默认状态 + * + * @param id 编号 + * @param defaultStatus 默认状态 + */ + void updateWarehouseDefaultStatus(Long id, Boolean defaultStatus); + + /** + * 删除仓库 + * + * @param id 编号 + */ + void deleteWarehouse(Long id); + + /** + * 获得仓库 + * + * @param id 编号 + * @return 仓库 + */ + ErpWarehouseDO getWarehouse(Long id); + + /** + * 校验仓库列表的有效性 + * + * @param ids 编号数组 + * @return 仓库列表 + */ + List validWarehouseList(Collection ids); + + /** + * 获得指定状态的仓库列表 + * + * @param status 状态 + * @return 仓库列表 + */ + List getWarehouseListByStatus(Integer status); + + /** + * 获得仓库列表 + * + * @param ids 编号数组 + * @return 仓库列表 + */ + List getWarehouseList(Collection ids); + + /** + * 获得仓库 Map + * + * @param ids 编号数组 + * @return 仓库 Map + */ + default Map getWarehouseMap(Collection ids) { + return convertMap(getWarehouseList(ids), ErpWarehouseDO::getId); + } + + /** + * 获得仓库分页 + * + * @param pageReqVO 分页查询 + * @return 仓库分页 + */ + PageResult getWarehousePage(ErpWarehousePageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java new file mode 100644 index 000000000..789209cba --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java @@ -0,0 +1,126 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.ErpWarehouseSaveReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehousePageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpWarehouseMapper; +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.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_NOT_ENABLE; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_NOT_EXISTS; + +/** + * ERP 仓库 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpWarehouseServiceImpl implements ErpWarehouseService { + + @Resource + private ErpWarehouseMapper warehouseMapper; + + @Override + public Long createWarehouse(ErpWarehouseSaveReqVO createReqVO) { + // 插入 + ErpWarehouseDO warehouse = BeanUtils.toBean(createReqVO, ErpWarehouseDO.class); + warehouseMapper.insert(warehouse); + // 返回 + return warehouse.getId(); + } + + @Override + public void updateWarehouse(ErpWarehouseSaveReqVO updateReqVO) { + // 校验存在 + validateWarehouseExists(updateReqVO.getId()); + // 更新 + ErpWarehouseDO updateObj = BeanUtils.toBean(updateReqVO, ErpWarehouseDO.class); + warehouseMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateWarehouseDefaultStatus(Long id, Boolean defaultStatus) { + // 1. 校验存在 + validateWarehouseExists(id); + + // 2.1 如果开启,则需要关闭所有其它的默认 + if (defaultStatus) { + ErpWarehouseDO warehouse = warehouseMapper.selectByDefaultStatus(); + if (warehouse != null) { + warehouseMapper.updateById(new ErpWarehouseDO().setId(warehouse.getId()).setDefaultStatus(false)); + } + } + // 2.2 更新对应的默认状态 + warehouseMapper.updateById(new ErpWarehouseDO().setId(id).setDefaultStatus(defaultStatus)); + } + + @Override + public void deleteWarehouse(Long id) { + // 校验存在 + validateWarehouseExists(id); + // 删除 + warehouseMapper.deleteById(id); + } + + private void validateWarehouseExists(Long id) { + if (warehouseMapper.selectById(id) == null) { + throw exception(WAREHOUSE_NOT_EXISTS); + } + } + + @Override + public ErpWarehouseDO getWarehouse(Long id) { + return warehouseMapper.selectById(id); + } + + @Override + public List validWarehouseList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + List list = warehouseMapper.selectBatchIds(ids); + Map warehouseMap = convertMap(list, ErpWarehouseDO::getId); + for (Long id : ids) { + ErpWarehouseDO warehouse = warehouseMap.get(id); + if (warehouseMap.get(id) == null) { + throw exception(WAREHOUSE_NOT_EXISTS); + } + if (CommonStatusEnum.isDisable(warehouse.getStatus())) { + throw exception(WAREHOUSE_NOT_ENABLE, warehouse.getName()); + } + } + return list; + } + + @Override + public List getWarehouseListByStatus(Integer status) { + return warehouseMapper.selectListByStatus(status); + } + + @Override + public List getWarehouseList(Collection ids) { + return warehouseMapper.selectBatchIds(ids); + } + + @Override + public PageResult getWarehousePage(ErpWarehousePageReqVO pageReqVO) { + return warehouseMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/bo/ErpStockRecordCreateReqBO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/bo/ErpStockRecordCreateReqBO.java new file mode 100644 index 000000000..40c62a4ef --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/bo/ErpStockRecordCreateReqBO.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.erp.service.stock.bo; + +import javax.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + * 库存明细的创建 Request BO + * + * @author 芋道源码 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockRecordCreateReqBO { + + /** + * 产品编号 + */ + @NotNull(message = "产品编号不能为空") + private Long productId; + /** + * 仓库编号 + */ + @NotNull(message = "仓库编号不能为空") + private Long warehouseId; + /** + * 出入库数量 + * + * 正数,表示入库;负数,表示出库 + */ + @NotNull(message = "出入库数量不能为空") + private BigDecimal count; + + /** + * 业务类型 + */ + @NotNull(message = "业务类型不能为空") + private Integer bizType; + /** + * 业务编号 + */ + @NotNull(message = "业务编号不能为空") + private Long bizId; + /** + * 业务项编号 + */ + @NotNull(message = "业务项编号不能为空") + private Long bizItemId; + /** + * 业务单号 + */ + @NotNull(message = "业务单号不能为空") + private String bizNo; + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/finance/ErpAccountMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/finance/ErpAccountMapper.xml new file mode 100644 index 000000000..a3cf6877b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/finance/ErpAccountMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/product/ErpProductUnitMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/product/ErpProductUnitMapper.xml new file mode 100644 index 000000000..4666e48d4 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/product/ErpProductUnitMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/sale/ErpCustomerMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/sale/ErpCustomerMapper.xml new file mode 100644 index 000000000..c012f4467 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/sale/ErpCustomerMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/stock/ErpWarehouseMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/stock/ErpWarehouseMapper.xml new file mode 100644 index 000000000..be2bc61cb --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/stock/ErpWarehouseMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/supplier/ErpSupplierMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/supplier/ErpSupplierMapper.xml new file mode 100644 index 000000000..54849af3f --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/supplier/ErpSupplierMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java index ceb6a8d5c..34522b881 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java @@ -8,9 +8,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileRespVO; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileUploadReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.*; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; import cn.iocoder.yudao.module.infra.service.file.FileService; import io.swagger.v3.oas.annotations.Operation; @@ -42,7 +40,7 @@ public class FileController { private FileService fileService; @PostMapping("/upload") - @Operation(summary = "上传文件") + @Operation(summary = "上传文件", description = "模式一:后端上传文件") @OperateLog(logArgs = false) // 上传文件,没有记录操作日志的必要 public CommonResult uploadFile(FileUploadReqVO uploadReqVO) throws Exception { MultipartFile file = uploadReqVO.getFile(); @@ -50,6 +48,18 @@ public class FileController { return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream()))); } + @GetMapping("/presigned-url") + @Operation(summary = "获取文件预签名地址", description = "模式二:前端上传文件:用于前端直接上传七牛、阿里云 OSS 等文件存储器") + public CommonResult getFilePresignedUrl(@RequestParam("path") String path) throws Exception { + return success(fileService.getFilePresignedUrl(path)); + } + + @PostMapping("/create") + @Operation(summary = "创建文件", description = "模式二:前端上传文件:配合 presigned-url 接口,记录上传了上传的文件") + public CommonResult createFile(@Valid @RequestBody FileCreateReqVO createReqVO) { + return success(fileService.createFile(createReqVO)); + } + @DeleteMapping("/delete") @Operation(summary = "删除文件") @Parameter(name = "id", description = "编号", required = true) @@ -62,7 +72,7 @@ public class FileController { @GetMapping("/{configId}/get/**") @PermitAll @Operation(summary = "下载文件") - @Parameter(name = "configId", description = "配置编号", required = true) + @Parameter(name = "configId", description = "配置编号", required = true) public void getFileContent(HttpServletRequest request, HttpServletResponse response, @PathVariable("configId") Long configId) throws Exception { diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileCreateReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileCreateReqVO.java new file mode 100644 index 000000000..24976189b --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileCreateReqVO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 文件创建 Request VO") +@Data +public class FileCreateReqVO { + + @NotNull(message = "文件配置编号不能为空") + @Schema(description = "文件配置编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11") + private Long configId; + + @NotNull(message = "文件路径不能为空") + @Schema(description = "文件路径", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao.jpg") + private String path; + + @NotNull(message = "原文件名不能为空") + @Schema(description = "原文件名", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao.jpg") + private String name; + + @NotNull(message = "文件 URL不能为空") + @Schema(description = "文件 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/yudao.jpg") + private String url; + + @Schema(description = "文件 MIME 类型", example = "application/octet-stream") + private String type; + + @Schema(description = "文件大小", example = "2048", requiredMode = Schema.RequiredMode.REQUIRED) + private Integer size; + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePresignedUrlRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePresignedUrlRespVO.java new file mode 100644 index 000000000..926133ebc --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePresignedUrlRespVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@Schema(description = "管理后台 - 文件预签名地址 Response VO") +@Data +public class FilePresignedUrlRespVO { + + @Schema(description = "配置编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11") + private Long configId; + + @Schema(description = "文件上传 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://s3.cn-south-1.qiniucs.com/ruoyi-vue-pro/758d3a5387507358c7236de4c8f96de1c7f5097ff6a7722b34772fb7b76b140f.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=3TvrJ70gl2Gt6IBe7_IZT1F6i_k0iMuRtyEv4EyS%2F20240217%2Fcn-south-1%2Fs3%2Faws4_request&X-Amz-Date=20240217T123222Z&X-Amz-Expires=600&X-Amz-SignedHeaders=host&X-Amz-Signature=a29f33770ab79bf523ccd4034d0752ac545f3c2a3b17baa1eb4e280cfdccfda5") + private String uploadUrl; + + /** + * 为什么要返回 url 字段? + * + * 前端上传完文件后,需要使用该 URL 进行访问 + */ + @Schema(description = "文件访问 URL", requiredMode = Schema.RequiredMode.REQUIRED, + example = "https://test.yudao.iocoder.cn/758d3a5387507358c7236de4c8f96de1c7f5097ff6a7722b34772fb7b76b140f.png") + private String url; + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java index 24baf4218..3ca9a2419 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java @@ -1,7 +1,9 @@ package cn.iocoder.yudao.module.infra.service.file; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileCreateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePresignedUrlRespVO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; /** @@ -22,13 +24,21 @@ public interface FileService { /** * 保存文件,并返回文件的访问路径 * - * @param name 文件名称 - * @param path 文件路径 + * @param name 文件名称 + * @param path 文件路径 * @param content 文件内容 * @return 文件路径 */ String createFile(String name, String path, byte[] content); + /** + * 创建文件 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createFile(FileCreateReqVO createReqVO); + /** * 删除文件 * @@ -40,9 +50,17 @@ public interface FileService { * 获得文件内容 * * @param configId 配置编号 - * @param path 文件路径 + * @param path 文件路径 * @return 文件内容 */ byte[] getFileContent(Long configId, String path) throws Exception; + /** + * 生成文件预签名地址信息 + * + * @param path 文件路径 + * @return 预签名地址信息 + */ + FilePresignedUrlRespVO getFilePresignedUrl(String path) throws Exception; + } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java index 0732765d8..05e38e957 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java @@ -4,9 +4,13 @@ import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.io.FileUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.file.core.client.FileClient; +import cn.iocoder.yudao.framework.file.core.client.s3.FilePresignedUrlRespDTO; import cn.iocoder.yudao.framework.file.core.utils.FileTypeUtils; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileCreateReqVO; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePresignedUrlRespVO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; import cn.iocoder.yudao.module.infra.dal.mysql.file.FileMapper; import lombok.SneakyThrows; @@ -66,6 +70,13 @@ public class FileServiceImpl implements FileService { return url; } + @Override + public Long createFile(FileCreateReqVO createReqVO) { + FileDO file = BeanUtils.toBean(createReqVO, FileDO.class); + fileMapper.insert(file); + return file.getId(); + } + @Override public void deleteFile(Long id) throws Exception { // 校验存在 @@ -95,4 +106,12 @@ public class FileServiceImpl implements FileService { return client.getContent(path); } + @Override + public FilePresignedUrlRespVO getFilePresignedUrl(String path) throws Exception { + FileClient fileClient = fileConfigService.getMasterFileClient(); + FilePresignedUrlRespDTO presignedObjectUrl = fileClient.getPresignedObjectUrl(path); + return BeanUtils.toBean(presignedObjectUrl, FilePresignedUrlRespVO.class, + object -> object.setConfigId(fileClient.getId())); + } + } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm index 7c2ab277b..c3044fb87 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm @@ -5,13 +5,12 @@ import request from '@/config/axios' export interface ${simpleClassName}VO { #foreach ($column in $columns) #if ($column.createOperation || $column.updateOperation) - // ${column.columnComment} #if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "short" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal") - ${column.javaField}: number + ${column.javaField}: number // ${column.columnComment} #elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdate" || ${column.javaType.toLowerCase()} == "localdatetime") - ${column.javaField}: Date + ${column.javaField}: Date // ${column.columnComment} #else - ${column.javaField}: ${column.javaType.toLowerCase()} + ${column.javaField}: ${column.javaType.toLowerCase()} // ${column.columnComment} #end #end #end diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/form.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/form.vue.vm index 14a72d264..8e3596b4f 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/form.vue.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/form.vue.vm @@ -244,7 +244,7 @@ const submitForm = async () => { // 提交请求 formLoading.value = true try { - const data = formData.value as unknown as ${simpleClassName}Api.${simpleClassName}VO + const data = formData.value as unknown as ${simpleClassName}VO ## 特殊:主子表专属逻辑 #if ( $table.templateType == 10 || $table.templateType == 12 ) #if ( $subTables && $subTables.size() > 0 ) diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm index a76dbaa82..361d379fa 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm @@ -259,8 +259,7 @@ const loading = ref(true) // 列表的加载中 const list = ref<${simpleClassName}VO[]>([]) // 列表的数据 ## 特殊:树表专属逻辑(树不需要分页接口) #if ( $table.templateType != 2 ) -// 列表的总页数 -const total = ref(0) +const total = ref(0) // 列表的总页数 #end const queryParams = reactive({ ## 特殊:树表专属逻辑(树不需要分页接口) diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApi.java index f8059fbb7..bdc3ba59b 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApi.java @@ -50,4 +50,12 @@ public interface DeptApi { return CollectionUtils.convertMap(list, DeptRespDTO::getId); } + /** + * 获得指定部门的所有子部门 + * + * @param id 部门编号 + * @return 子部门列表 + */ + List getChildDeptList(Long id); + } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java index b6cab3030..cea3c3663 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -65,6 +66,17 @@ public interface AdminUserApi { return CollectionUtils.convertMap(users, AdminUserRespDTO::getId); } + /** + * 校验用户是否有效。如下情况,视为无效: + * 1. 用户编号不存在 + * 2. 用户被禁用 + * + * @param id 用户编号 + */ + default void validateUser(Long id) { + validateUserList(Collections.singleton(id)); + } + /** * 校验用户们是否有效。如下情况,视为无效: * 1. 用户编号不存在 diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java index ef5c3a624..2f41f67e9 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java @@ -98,7 +98,7 @@ public interface ErrorCodeConstants { ErrorCode SMS_CODE_USED = new ErrorCode(1_002_014_002, "验证码已使用"); ErrorCode SMS_CODE_NOT_CORRECT = new ErrorCode(1_002_014_003, "验证码不正确"); ErrorCode SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1_002_014_004, "超过每日短信发送数量"); - ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1_002_014_005, "短信发送过于频率"); + ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1_002_014_005, "短信发送过于频繁"); ErrorCode SMS_CODE_IS_EXISTS = new ErrorCode(1_002_014_006, "手机号已被使用"); ErrorCode SMS_CODE_IS_UNUSED = new ErrorCode(1_002_014_007, "验证码未被使用"); diff --git a/yudao-module-system/yudao-module-system-biz/pom.xml b/yudao-module-system/yudao-module-system-biz/pom.xml index 535a91ab0..49ddf4e04 100644 --- a/yudao-module-system/yudao-module-system-biz/pom.xml +++ b/yudao-module-system/yudao-module-system-biz/pom.xml @@ -34,10 +34,6 @@ cn.iocoder.boot yudao-spring-boot-starter-biz-operatelog - - cn.iocoder.boot - yudao-spring-boot-starter-biz-sms - cn.iocoder.boot yudao-spring-boot-starter-biz-dict @@ -120,6 +116,18 @@ wx-java-miniapp-spring-boot-starter + + com.aliyun + aliyun-java-sdk-core + + + com.aliyun + aliyun-java-sdk-dysmsapi + + + com.tencentcloudapi + tencentcloud-sdk-java-sms + diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java index 8d11bdcf4..b040a75c7 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.service.dept.DeptService; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -38,4 +39,10 @@ public class DeptApiImpl implements DeptApi { deptService.validateDeptList(ids); } + @Override + public List getChildDeptList(Long id) { + List childDeptList = deptService.getChildDeptList(id); + return BeanUtils.toBean(childDeptList, DeptRespDTO.class); + } + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java index 54aaa4dc7..c26acb8ca 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java @@ -44,6 +44,9 @@ public class AuthPermissionInfoRespVO { @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.jpg") private String avatar; + @Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") + private Long deptId; + } @Schema(description = "管理后台 - 登录用户的菜单信息 Response VO") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeSaveReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeSaveReqVO.java index 1618498a7..200aadd92 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeSaveReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeSaveReqVO.java @@ -11,8 +11,7 @@ import javax.validation.constraints.Size; @Data public class NoticeSaveReqVO { - @Schema(description = "岗位公告编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") -// @NotNull(message = "岗位公告编号不能为空") + @Schema(description = "岗位公告编号", example = "1024") private Long id; @Schema(description = "公告标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "小博主") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsCallbackController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsCallbackController.java index b660f8b2b..a4e8255aa 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsCallbackController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsCallbackController.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.system.controller.admin.sms; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.framework.sms.core.enums.SmsChannelEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsChannelEnum; import cn.iocoder.yudao.module.system.service.sms.SmsSendService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java index 8343547d9..18463e7f6 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.system.convert.auth; import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO; import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; @@ -29,7 +30,7 @@ public interface AuthConvert { default AuthPermissionInfoRespVO convert(AdminUserDO user, List roleList, List menuList) { return AuthPermissionInfoRespVO.builder() - .user(AuthPermissionInfoRespVO.UserVO.builder().id(user.getId()).nickname(user.getNickname()).avatar(user.getAvatar()).build()) + .user(BeanUtils.toBean(user, AuthPermissionInfoRespVO.UserVO.class)) .roles(convertSet(roleList, RoleDO::getCode)) // 权限标识信息 .permissions(convertSet(menuList, MenuDO::getPermission)) diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsChannelDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsChannelDO.java index c57ea5b59..6ecb4f142 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsChannelDO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsChannelDO.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.sms; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.framework.sms.core.enums.SmsChannelEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsChannelEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/SmsCodeConfiguration.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/SmsCodeConfiguration.java deleted file mode 100644 index ddc70a39e..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/SmsCodeConfiguration.java +++ /dev/null @@ -1,9 +0,0 @@ -package cn.iocoder.yudao.module.system.framework.sms; - -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -@Configuration(proxyBeanMethods = false) -@EnableConfigurationProperties(SmsCodeProperties.class) -public class SmsCodeConfiguration { -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/SmsCodeProperties.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/config/SmsCodeProperties.java similarity index 94% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/SmsCodeProperties.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/config/SmsCodeProperties.java index 5d246bad7..4f3a50c3f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/SmsCodeProperties.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/config/SmsCodeProperties.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.system.framework.sms; +package cn.iocoder.yudao.module.system.framework.sms.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/config/SmsConfiguration.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/config/SmsConfiguration.java new file mode 100644 index 000000000..eb34775fe --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/config/SmsConfiguration.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.system.framework.sms.config; + +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClientFactory; +import cn.iocoder.yudao.module.system.framework.sms.core.client.impl.SmsClientFactoryImpl; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 短信配置类,包括短信客户端、短信验证码两部分 + * + * @author 芋道源码 + */ +@Configuration(proxyBeanMethods = false) +@EnableConfigurationProperties(SmsCodeProperties.class) +public class SmsConfiguration { + + @Bean + public SmsClientFactory smsClientFactory() { + return new SmsClientFactoryImpl(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsClient.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/SmsClient.java similarity index 80% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsClient.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/SmsClient.java index ef945a329..46224663c 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsClient.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/SmsClient.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.framework.sms.core.client; +package cn.iocoder.yudao.module.system.framework.sms.core.client; import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO; import java.util.List; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsClientFactory.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/SmsClientFactory.java similarity index 79% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsClientFactory.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/SmsClientFactory.java index d063e58f3..a1133177f 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsClientFactory.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/SmsClientFactory.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.framework.sms.core.client; +package cn.iocoder.yudao.module.system.framework.sms.core.client; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; +import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; /** * 短信客户端的工厂接口 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsReceiveRespDTO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/dto/SmsReceiveRespDTO.java similarity index 91% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsReceiveRespDTO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/dto/SmsReceiveRespDTO.java index 4def4a25c..c90a33e63 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsReceiveRespDTO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/dto/SmsReceiveRespDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.sms.core.client.dto; +package cn.iocoder.yudao.module.system.framework.sms.core.client.dto; import lombok.Data; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsSendRespDTO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/dto/SmsSendRespDTO.java similarity index 91% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsSendRespDTO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/dto/SmsSendRespDTO.java index ec517508a..9f3094bcb 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsSendRespDTO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/dto/SmsSendRespDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.sms.core.client.dto; +package cn.iocoder.yudao.module.system.framework.sms.core.client.dto; import lombok.Data; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsTemplateRespDTO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/dto/SmsTemplateRespDTO.java similarity index 73% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsTemplateRespDTO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/dto/SmsTemplateRespDTO.java index 70e8df400..38a43aa28 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsTemplateRespDTO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/dto/SmsTemplateRespDTO.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.framework.sms.core.client.dto; +package cn.iocoder.yudao.module.system.framework.sms.core.client.dto; -import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum; import lombok.Data; /** diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/AbstractSmsClient.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AbstractSmsClient.java similarity index 82% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/AbstractSmsClient.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AbstractSmsClient.java index a3b92d5c3..3b6e0eb0d 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/AbstractSmsClient.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AbstractSmsClient.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl; +package cn.iocoder.yudao.module.system.framework.sms.core.client.impl; -import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient; +import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; import lombok.extern.slf4j.Slf4j; /** diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient.java similarity index 92% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient.java index d32a5bb11..7d01e6cdf 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient.java @@ -1,15 +1,14 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.aliyun; +package cn.iocoder.yudao.module.system.framework.sms.core.client.impl; import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.impl.AbstractSmsClient; -import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.IAcsClient; import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/DebugDingTalkSmsClient.java similarity index 87% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/DebugDingTalkSmsClient.java index 315edf942..e9fcc6c41 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/DebugDingTalkSmsClient.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.debug; +package cn.iocoder.yudao.module.system.framework.sms.core.client.impl; import cn.hutool.core.codec.Base64; import cn.hutool.core.lang.Assert; @@ -10,12 +10,11 @@ import cn.hutool.http.HttpUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.impl.AbstractSmsClient; -import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; import java.util.HashMap; import java.util.List; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/SmsClientFactoryImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/SmsClientFactoryImpl.java similarity index 84% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/SmsClientFactoryImpl.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/SmsClientFactoryImpl.java index abb7dda1b..94fe88da9 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/SmsClientFactoryImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/SmsClientFactoryImpl.java @@ -1,12 +1,9 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl; +package cn.iocoder.yudao.module.system.framework.sms.core.client.impl; -import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; -import cn.iocoder.yudao.framework.sms.core.client.impl.aliyun.AliyunSmsClient; -import cn.iocoder.yudao.framework.sms.core.client.impl.debug.DebugDingTalkSmsClient; -import cn.iocoder.yudao.framework.sms.core.client.impl.tencent.TencentSmsClient; -import cn.iocoder.yudao.framework.sms.core.enums.SmsChannelEnum; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient; +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClientFactory; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsChannelEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; import lombok.extern.slf4j.Slf4j; import org.springframework.util.Assert; import org.springframework.validation.annotation.Validated; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClient.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/TencentSmsClient.java similarity index 93% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClient.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/TencentSmsClient.java index eeb287ffe..dc238be77 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClient.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/TencentSmsClient.java @@ -1,16 +1,15 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.tencent; +package cn.iocoder.yudao.module.system.framework.sms.core.client.impl; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.impl.AbstractSmsClient; -import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.annotations.VisibleForTesting; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsChannelEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/enums/SmsChannelEnum.java similarity index 91% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsChannelEnum.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/enums/SmsChannelEnum.java index 66410bd2c..7bd192223 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsChannelEnum.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/enums/SmsChannelEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.sms.core.enums; +package cn.iocoder.yudao.module.system.framework.sms.core.enums; import cn.hutool.core.util.ArrayUtil; import lombok.AllArgsConstructor; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java similarity index 81% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java index 255565002..489f69e45 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.sms.core.enums; +package cn.iocoder.yudao.module.system.framework.sms.core.enums; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/property/SmsChannelProperties.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/property/SmsChannelProperties.java similarity index 87% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/property/SmsChannelProperties.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/property/SmsChannelProperties.java index 943184b03..793b049e5 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/property/SmsChannelProperties.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/property/SmsChannelProperties.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.framework.sms.core.property; +package cn.iocoder.yudao.module.system.framework.sms.core.property; -import cn.iocoder.yudao.framework.sms.core.enums.SmsChannelEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsChannelEnum; import lombok.Data; import org.springframework.validation.annotation.Validated; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelService.java index c820630da..5c77fe1a3 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelService.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.system.service.sms; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.sms.core.client.SmsClient; +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceImpl.java index 0187bbee9..a7455f152 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceImpl.java @@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.system.service.sms; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient; +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClientFactory; +import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImpl.java index 682b89eff..79162c623 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImpl.java @@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeValidateReqDTO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsCodeDO; import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsCodeMapper; import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; -import cn.iocoder.yudao.module.system.framework.sms.SmsCodeProperties; +import cn.iocoder.yudao.module.system.framework.sms.config.SmsCodeProperties; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImpl.java index 4650bd4f8..49af0ecea 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImpl.java @@ -8,9 +8,9 @@ import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; -import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImpl.java index 219710f27..639bec612 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImpl.java @@ -7,9 +7,9 @@ import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index 20b67725b..bc850b590 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -31,10 +31,6 @@ yudao-module-infra-biz ${revision} - - cn.iocoder.boot - yudao-spring-boot-starter-biz-error-code - @@ -96,6 +92,13 @@ + + + + + + + @@ -104,10 +107,6 @@ spring-boot-configuration-processor true - - cn.iocoder.boot - yudao-spring-boot-starter-banner - diff --git a/yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java b/yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java index ab626b1e7..7aba89997 100644 --- a/yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java +++ b/yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java @@ -35,6 +35,12 @@ public class DefaultController { "[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]"); } + @RequestMapping("/admin-api/erp/**") + public CommonResult erp404() { + return CommonResult.error(NOT_IMPLEMENTED.getCode(), + "[ERP 模块 yudao-module-erp - 已禁用][参考 https://doc.iocoder.cn/erp/build/ 开启]"); + } + @RequestMapping(value = {"/admin-api/report/**"}) public CommonResult report404() { return CommonResult.error(NOT_IMPLEMENTED.getCode(), diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 311cd4eb8..5996782b0 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -188,6 +188,7 @@ logging: cn.iocoder.yudao.module.promotion.dal.mysql: debug cn.iocoder.yudao.module.statistics.dal.mysql: debug cn.iocoder.yudao.module.crm.dal.mysql: debug + cn.iocoder.yudao.module.erp.dal.mysql: debug org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示 debug: false