From 43f2f054e909d0e0214c811137998d7fe1ffdd57 Mon Sep 17 00:00:00 2001 From: kkfluous Date: Thu, 12 Mar 2026 21:09:06 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E4=BE=9B=E5=BA=94?= =?UTF-8?q?=E5=95=86=E7=AE=A1=E7=90=86=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增供应商管理功能 - 数据库表:asset_supplier(27个字段) - 基本信息:供应商编码、名称、类型、合作状态等 - 开票信息:税号、开票地址、账号、开户行等 - 完整的 CRUD 接口 - 后端代码 - Controller/Service/Mapper/VO/DO 完整实现 - 支持多条件分页查询 - 字段验证(手机号、邮箱格式) - 供应商编码唯一性约束 - API 接口 - POST /asset/supplier/create - 创建供应商 - PUT /asset/supplier/update - 更新供应商 - DELETE /asset/supplier/delete - 删除供应商 - GET /asset/supplier/get - 获取供应商详情 - GET /asset/supplier/page - 分页查询供应商 - 查询功能 - 供应商编码精确查询 - 合作状态多选筛选 - 供应商名称模糊查询 - 供应商类型多选筛选 - 区域多选筛选 - 城市精确查询 - 创建者筛选 - 菜单和权限 - 供应商管理菜单 - 5个按钮权限(查询、创建、更新、删除、导出) - 文档 - 供应商管理模块开发总结 - 数据库初始化脚本 --- .../SUPPLIER_MANAGEMENT_SUMMARY.md | 353 ++++++++++++++++++ yudao-module-asset/sql/mysql/supplier.sql | 66 ++++ .../admin/supplier/SupplierController.java | 78 ++++ .../admin/supplier/vo/SupplierBaseVO.java | 84 +++++ .../admin/supplier/vo/SupplierPageReqVO.java | 43 +++ .../admin/supplier/vo/SupplierRespVO.java | 36 ++ .../admin/supplier/vo/SupplierSaveReqVO.java | 22 ++ .../convert/supplier/SupplierConvert.java | 26 ++ .../dal/dataobject/supplier/SupplierDO.java | 130 +++++++ .../dal/mysql/supplier/SupplierMapper.java | 30 ++ .../asset/enums/ErrorCodeConstants.java | 3 + .../service/supplier/SupplierService.java | 55 +++ .../service/supplier/SupplierServiceImpl.java | 83 ++++ 13 files changed, 1009 insertions(+) create mode 100644 yudao-module-asset/SUPPLIER_MANAGEMENT_SUMMARY.md create mode 100644 yudao-module-asset/sql/mysql/supplier.sql create mode 100644 yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/supplier/SupplierController.java create mode 100644 yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/supplier/vo/SupplierBaseVO.java create mode 100644 yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/supplier/vo/SupplierPageReqVO.java create mode 100644 yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/supplier/vo/SupplierRespVO.java create mode 100644 yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/supplier/vo/SupplierSaveReqVO.java create mode 100644 yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/supplier/SupplierConvert.java create mode 100644 yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/supplier/SupplierDO.java create mode 100644 yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/supplier/SupplierMapper.java create mode 100644 yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/supplier/SupplierService.java create mode 100644 yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/supplier/SupplierServiceImpl.java diff --git a/yudao-module-asset/SUPPLIER_MANAGEMENT_SUMMARY.md b/yudao-module-asset/SUPPLIER_MANAGEMENT_SUMMARY.md new file mode 100644 index 0000000..b2a40bf --- /dev/null +++ b/yudao-module-asset/SUPPLIER_MANAGEMENT_SUMMARY.md @@ -0,0 +1,353 @@ +# 供应商管理模块开发总结 + +## 📋 需求来源 + +根据 ONE-OS 前端原型 `/Users/kkfluous/Projects/ai-coding/ln-oneos/ONE-OS/web端/业务管理/供应商管理*.jsx` 进行后端设计开发。 + +## 🎯 功能概述 + +供应商管理模块用于管理企业的各类供应商信息,包括加氢站、充电站、维修站、保险公司、备件供应商等。 + +### 核心功能 +- ✅ 供应商列表查询(支持多条件筛选) +- ✅ 供应商新增 +- ✅ 供应商编辑 +- ✅ 供应商查看 +- ✅ 供应商删除 +- 🔲 供应商导入(待实现) +- 🔲 供应商导出(待实现) + +## 📊 数据模型 + +### 供应商信息表 (asset_supplier) + +#### 基本信息 +| 字段 | 类型 | 说明 | 必填 | +|------|------|------|------| +| id | BIGINT | 主键ID | ✓ | +| supplier_code | VARCHAR(50) | 供应商编码 | ✓ | +| coop_status | VARCHAR(20) | 合作状态 | ✓ | +| supplier_name | VARCHAR(100) | 供应商名称 | ✓ | +| type | VARCHAR(50) | 供应商类型 | ✓ | +| province | VARCHAR(50) | 省份 | | +| city | VARCHAR(50) | 城市 | | +| address | VARCHAR(255) | 详细地址 | | +| region | VARCHAR(20) | 区域 | | +| contact | VARCHAR(50) | 联系人 | | +| contact_mobile | VARCHAR(20) | 联系手机 | | +| contact_phone | VARCHAR(50) | 联系电话 | | +| email | VARCHAR(100) | 邮箱 | | +| credit_code_or_id | VARCHAR(100) | 统一社会信用代码/身份证号 | | +| remark | VARCHAR(500) | 备注 | | + +#### 开票信息 +| 字段 | 类型 | 说明 | +|------|------|------| +| tax_id | VARCHAR(100) | 税号 | +| invoice_address | VARCHAR(255) | 开票地址 | +| invoice_phone | VARCHAR(50) | 开票电话 | +| account | VARCHAR(100) | 账号 | +| opening_bank | VARCHAR(200) | 开户行 | +| mailing_address | VARCHAR(255) | 邮寄地址 | + +#### 审计字段 +| 字段 | 类型 | 说明 | +|------|------|------| +| creator | VARCHAR(64) | 创建者 | +| create_time | DATETIME | 创建时间 | +| updater | VARCHAR(64) | 更新者 | +| update_time | DATETIME | 更新时间 | +| deleted | BIT(1) | 是否删除 | +| tenant_id | BIGINT | 租户编号 | + +### 索引设计 +- PRIMARY KEY: `id` +- UNIQUE KEY: `uk_supplier_code` (supplier_code, deleted) +- INDEX: `idx_supplier_name` (supplier_name) +- INDEX: `idx_coop_status` (coop_status) +- INDEX: `idx_type` (type) +- INDEX: `idx_region` (region) +- INDEX: `idx_city` (city) +- INDEX: `idx_create_time` (create_time) +- INDEX: `idx_tenant_id` (tenant_id) + +## 🏗️ 代码结构 + +### 后端文件清单 + +``` +yudao-module-asset/yudao-module-asset-server/ +├── src/main/java/cn/iocoder/yudao/module/asset/ +│ ├── controller/admin/supplier/ +│ │ ├── SupplierController.java # 控制器 +│ │ └── vo/ +│ │ ├── SupplierBaseVO.java # 基础 VO +│ │ ├── SupplierSaveReqVO.java # 创建/更新 Request VO +│ │ ├── SupplierRespVO.java # 响应 VO +│ │ └── SupplierPageReqVO.java # 分页查询 Request VO +│ ├── service/supplier/ +│ │ ├── SupplierService.java # Service 接口 +│ │ └── SupplierServiceImpl.java # Service 实现 +│ ├── convert/supplier/ +│ │ └── SupplierConvert.java # 对象转换 +│ ├── dal/ +│ │ ├── dataobject/supplier/ +│ │ │ └── SupplierDO.java # 数据对象 +│ │ └── mysql/supplier/ +│ │ └── SupplierMapper.java # Mapper +│ └── enums/ +│ └── ErrorCodeConstants.java # 错误码(已更新) +└── sql/mysql/ + └── supplier.sql # 数据库脚本 +``` + +## 🔌 API 接口 + +### 基础路径 +``` +/asset/supplier +``` + +### 接口列表 + +#### 1. 创建供应商 +``` +POST /asset/supplier/create +权限: asset:supplier:create +``` + +**Request Body** +```json +{ + "supplierCode": "GYS-2025-001", + "coopStatus": "已合作", + "supplierName": "嘉兴某某加氢站", + "type": "加氢站", + "province": "浙江省", + "city": "嘉兴市", + "address": "浙江省嘉兴市南湖区科技大道1号", + "region": "华东", + "contact": "张三", + "contactMobile": "13800138001", + "contactPhone": "0571-88888888", + "email": "zhangsan@example.com", + "creditCodeOrId": "91330400MA2XXXXX1", + "remark": "", + "taxId": "91330400MA2XXXXX1", + "invoiceAddress": "浙江省嘉兴市南湖区科技大道1号", + "invoicePhone": "0571-88888888", + "account": "6222021234567890123", + "openingBank": "中国工商银行嘉兴分行", + "mailingAddress": "浙江省嘉兴市南湖区科技大道1号" +} +``` + +**Response** +```json +{ + "code": 0, + "data": 1, + "msg": "操作成功" +} +``` + +#### 2. 更新供应商 +``` +PUT /asset/supplier/update +权限: asset:supplier:update +``` + +**Request Body** +```json +{ + "id": 1, + "supplierCode": "GYS-2025-001", + "coopStatus": "已合作", + "supplierName": "嘉兴某某加氢站", + ... +} +``` + +#### 3. 删除供应商 +``` +DELETE /asset/supplier/delete?id=1 +权限: asset:supplier:delete +``` + +#### 4. 获取供应商详情 +``` +GET /asset/supplier/get?id=1 +权限: asset:supplier:query +``` + +**Response** +```json +{ + "code": 0, + "data": { + "id": 1, + "supplierCode": "GYS-2025-001", + "coopStatus": "已合作", + "supplierName": "嘉兴某某加氢站", + "type": "加氢站", + "province": "浙江省", + "city": "嘉兴市", + "address": "浙江省嘉兴市南湖区科技大道1号", + "region": "华东", + "contact": "张三", + "contactMobile": "13800138001", + "contactPhone": "0571-88888888", + "email": "zhangsan@example.com", + "creditCodeOrId": "91330400MA2XXXXX1", + "remark": "", + "taxId": "91330400MA2XXXXX1", + "invoiceAddress": "浙江省嘉兴市南湖区科技大道1号", + "invoicePhone": "0571-88888888", + "account": "6222021234567890123", + "openingBank": "中国工商银行嘉兴分行", + "mailingAddress": "浙江省嘉兴市南湖区科技大道1号", + "creator": "admin", + "createTime": "2025-01-10T09:30:00", + "updater": "admin", + "updateTime": "2025-01-10T09:30:00" + }, + "msg": "操作成功" +} +``` + +#### 5. 分页查询供应商 +``` +GET /asset/supplier/page +权限: asset:supplier:query +``` + +**Query Parameters** +- `pageNo`: 页码(默认 1) +- `pageSize`: 每页数量(默认 10) +- `supplierCode`: 供应商编码(精确匹配) +- `coopStatus`: 合作状态列表(多选) +- `supplierName`: 供应商名称(模糊查询) +- `type`: 供应商类型列表(多选) +- `region`: 区域列表(多选) +- `city`: 城市(精确匹配) +- `creator`: 创建者(精确匹配) + +**Response** +```json +{ + "code": 0, + "data": { + "list": [...], + "total": 100 + }, + "msg": "操作成功" +} +``` + +## 📚 字典数据 + +### 合作状态 (coop_status) +- 已合作 +- 终止合作 +- 洽谈中 +- 合约过期 + +### 供应商类型 (type) +- 备件供应商 +- 保险公司 +- 加氢站 +- 充电站 +- 维修站 +- 救援车队 +- 整车厂 +- 其他 + +### 区域 (region) +- 华北 +- 华东 +- 华南 +- 华中 +- 东北 +- 西南 +- 西北 + +## ✅ 已完成工作 + +### 1. 数据库设计 +- ✅ 创建 `asset_supplier` 表 +- ✅ 设计合理的索引 +- ✅ 添加菜单和权限配置 + +### 2. 后端代码 +- ✅ DO (Data Object) +- ✅ Mapper +- ✅ VO (View Object) +- ✅ Convert (对象转换) +- ✅ Service 接口和实现 +- ✅ Controller +- ✅ 错误码常量 + +### 3. 编译验证 +- ✅ Maven 编译通过 +- ✅ 无语法错误 + +### 4. 数据库初始化 +- ✅ 供应商表创建成功(27 个字段) +- ✅ 菜单创建成功(ID: 5062) +- ✅ 5 个按钮权限创建成功 + +## 🔲 待完成工作 + +### 1. 导入导出功能 +- 🔲 Excel 导入模板设计 +- 🔲 Excel 导入功能实现 +- 🔲 Excel 导出功能实现 + +### 2. 数据字典配置 +- 🔲 在系统字典中配置合作状态 +- 🔲 在系统字典中配置供应商类型 + +### 3. 前端开发 +- 🔲 供应商列表页面 +- 🔲 供应商新增页面 +- 🔲 供应商编辑页面 +- 🔲 供应商查看页面 + +### 4. 测试 +- 🔲 单元测试 +- 🔲 集成测试 +- 🔲 API 接口测试 + +## 🎯 使用说明 + +### 启动服务 +1. 确保数据库已初始化 +2. 启动 `yudao-server` 应用 +3. 访问 Swagger 文档: `http://localhost:48080/doc.html` + +### API 测试 +使用 Postman 或 Swagger UI 测试接口: +1. 先登录获取 token +2. 在请求头中添加 `Authorization: Bearer {token}` +3. 调用供应商管理接口 + +## 📝 注意事项 + +1. **供应商编码唯一性**: `supplier_code` 字段有唯一索引,不能重复 +2. **手机号格式验证**: 使用正则表达式验证手机号格式 +3. **邮箱格式验证**: 使用 `@Email` 注解验证邮箱格式 +4. **软删除**: 使用 `deleted` 字段实现软删除,不会物理删除数据 +5. **多租户**: 支持多租户隔离,通过 `tenant_id` 字段区分 + +## 🔗 相关模块 + +- 客户管理模块 (Customer) +- 车辆管理模块 (Vehicle) +- 停车场管理模块 (Parking) +- 车型参数管理模块 (VehicleModel) + +--- + +**开发日期**: 2026-03-12 +**开发人员**: AI Assistant +**版本**: v1.0.0 diff --git a/yudao-module-asset/sql/mysql/supplier.sql b/yudao-module-asset/sql/mysql/supplier.sql new file mode 100644 index 0000000..95214b6 --- /dev/null +++ b/yudao-module-asset/sql/mysql/supplier.sql @@ -0,0 +1,66 @@ +-- 供应商信息表 +CREATE TABLE IF NOT EXISTS `asset_supplier` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `supplier_code` VARCHAR(50) NOT NULL COMMENT '供应商编码', + `coop_status` VARCHAR(20) NOT NULL COMMENT '合作状态', + `supplier_name` VARCHAR(100) NOT NULL COMMENT '供应商名称', + `type` VARCHAR(50) NOT NULL COMMENT '供应商类型', + `province` VARCHAR(50) COMMENT '省份', + `city` VARCHAR(50) COMMENT '城市', + `address` VARCHAR(255) COMMENT '详细地址', + `region` VARCHAR(20) COMMENT '区域', + `contact` VARCHAR(50) COMMENT '联系人', + `contact_mobile` VARCHAR(20) COMMENT '联系手机', + `contact_phone` VARCHAR(50) COMMENT '联系电话', + `email` VARCHAR(100) COMMENT '邮箱', + `credit_code_or_id` VARCHAR(100) COMMENT '统一社会信用代码/身份证号', + `remark` VARCHAR(500) COMMENT '备注', + + -- 开票信息 + `tax_id` VARCHAR(100) COMMENT '税号', + `invoice_address` VARCHAR(255) COMMENT '开票地址', + `invoice_phone` VARCHAR(50) COMMENT '开票电话', + `account` VARCHAR(100) COMMENT '账号', + `opening_bank` VARCHAR(200) COMMENT '开户行', + `mailing_address` VARCHAR(255) COMMENT '邮寄地址', + + -- 审计字段 + `creator` VARCHAR(64) DEFAULT '' COMMENT '创建者', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` VARCHAR(64) DEFAULT '' COMMENT '更新者', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号', + + PRIMARY KEY (`id`), + UNIQUE KEY `uk_supplier_code` (`supplier_code`, `deleted`), + INDEX `idx_supplier_name` (`supplier_name`), + INDEX `idx_coop_status` (`coop_status`), + INDEX `idx_type` (`type`), + INDEX `idx_region` (`region`), + INDEX `idx_city` (`city`), + INDEX `idx_create_time` (`create_time`), + INDEX `idx_tenant_id` (`tenant_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='供应商信息表'; + +-- 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '供应商管理', '', 2, 4, 5055, + 'supplier', 'user', 'asset/supplier/index', 0, 'Supplier' +); + +-- 获取刚插入的菜单ID +SET @menuId = LAST_INSERT_ID(); + +-- 供应商管理按钮权限 +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES + ('供应商查询', 'asset:supplier:query', 3, 1, @menuId, '', '', '', 0), + ('供应商创建', 'asset:supplier:create', 3, 2, @menuId, '', '', '', 0), + ('供应商更新', 'asset:supplier:update', 3, 3, @menuId, '', '', '', 0), + ('供应商删除', 'asset:supplier:delete', 3, 4, @menuId, '', '', '', 0), + ('供应商导出', 'asset:supplier:export', 3, 5, @menuId, '', '', '', 0); diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/supplier/SupplierController.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/supplier/SupplierController.java new file mode 100644 index 0000000..b89c5ad --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/supplier/SupplierController.java @@ -0,0 +1,78 @@ +package cn.iocoder.yudao.module.asset.controller.admin.supplier; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.asset.controller.admin.supplier.vo.SupplierPageReqVO; +import cn.iocoder.yudao.module.asset.controller.admin.supplier.vo.SupplierRespVO; +import cn.iocoder.yudao.module.asset.controller.admin.supplier.vo.SupplierSaveReqVO; +import cn.iocoder.yudao.module.asset.convert.supplier.SupplierConvert; +import cn.iocoder.yudao.module.asset.dal.dataobject.supplier.SupplierDO; +import cn.iocoder.yudao.module.asset.service.supplier.SupplierService; +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 jakarta.annotation.Resource; +import jakarta.validation.Valid; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +/** + * 供应商信息 Controller + * + * @author 芋道源码 + */ +@Tag(name = "管理后台 - 供应商信息") +@RestController +@RequestMapping("/asset/supplier") +@Validated +public class SupplierController { + + @Resource + private SupplierService supplierService; + + @PostMapping("/create") + @Operation(summary = "创建供应商") + @PreAuthorize("@ss.hasPermission('asset:supplier:create')") + public CommonResult createSupplier(@Valid @RequestBody SupplierSaveReqVO createReqVO) { + return success(supplierService.createSupplier(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新供应商") + @PreAuthorize("@ss.hasPermission('asset:supplier:update')") + public CommonResult updateSupplier(@Valid @RequestBody SupplierSaveReqVO updateReqVO) { + supplierService.updateSupplier(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除供应商") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('asset: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 = "1") + @PreAuthorize("@ss.hasPermission('asset:supplier:query')") + public CommonResult getSupplier(@RequestParam("id") Long id) { + SupplierDO supplier = supplierService.getSupplier(id); + return success(SupplierConvert.INSTANCE.convert(supplier)); + } + + @GetMapping("/page") + @Operation(summary = "获得供应商分页") + @PreAuthorize("@ss.hasPermission('asset:supplier:query')") + public CommonResult> getSupplierPage(@Valid SupplierPageReqVO pageReqVO) { + PageResult pageResult = supplierService.getSupplierPage(pageReqVO); + return success(SupplierConvert.INSTANCE.convertPage(pageResult)); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/supplier/vo/SupplierBaseVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/supplier/vo/SupplierBaseVO.java new file mode 100644 index 0000000..b741aca --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/supplier/vo/SupplierBaseVO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.asset.controller.admin.supplier.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.Pattern; + +/** + * 供应商信息 Base VO + * + * @author 芋道源码 + */ +@Data +public class SupplierBaseVO { + + @Schema(description = "供应商编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "GYS-2025-001") + @NotBlank(message = "供应商编码不能为空") + private String supplierCode; + + @Schema(description = "合作状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "已合作") + @NotBlank(message = "合作状态不能为空") + private String coopStatus; + + @Schema(description = "供应商名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "嘉兴某某加氢站") + @NotBlank(message = "供应商名称不能为空") + private String supplierName; + + @Schema(description = "供应商类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "加氢站") + @NotBlank(message = "供应商类型不能为空") + private String type; + + @Schema(description = "省份", example = "浙江省") + private String province; + + @Schema(description = "城市", example = "嘉兴市") + private String city; + + @Schema(description = "详细地址", example = "浙江省嘉兴市南湖区科技大道1号") + private String address; + + @Schema(description = "区域", example = "华东") + private String region; + + @Schema(description = "联系人", example = "张三") + private String contact; + + @Schema(description = "联系手机", example = "13800138001") + @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确") + private String contactMobile; + + @Schema(description = "联系电话", example = "0571-88888888") + private String contactPhone; + + @Schema(description = "邮箱", example = "zhangsan@example.com") + @Email(message = "邮箱格式不正确") + private String email; + + @Schema(description = "统一社会信用代码/身份证号", example = "91330400MA2XXXXX1") + private String creditCodeOrId; + + @Schema(description = "备注", example = "") + private String remark; + + @Schema(description = "税号", example = "91330400MA2XXXXX1") + private String taxId; + + @Schema(description = "开票地址", example = "浙江省嘉兴市南湖区科技大道1号") + private String invoiceAddress; + + @Schema(description = "开票电话", example = "0571-88888888") + private String invoicePhone; + + @Schema(description = "账号", example = "6222021234567890123") + private String account; + + @Schema(description = "开户行", example = "中国工商银行嘉兴分行") + private String openingBank; + + @Schema(description = "邮寄地址", example = "浙江省嘉兴市南湖区科技大道1号") + private String mailingAddress; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/supplier/vo/SupplierPageReqVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/supplier/vo/SupplierPageReqVO.java new file mode 100644 index 0000000..ffdafdb --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/supplier/vo/SupplierPageReqVO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.asset.controller.admin.supplier.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.util.List; + +/** + * 供应商信息 - 分页查询 Request VO + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - 供应商信息分页查询 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class SupplierPageReqVO extends PageParam { + + @Schema(description = "供应商编码", example = "GYS-2025-001") + private String supplierCode; + + @Schema(description = "合作状态列表", example = "[\"已合作\", \"洽谈中\"]") + private List coopStatus; + + @Schema(description = "供应商名称(模糊查询)", example = "加氢站") + private String supplierName; + + @Schema(description = "供应商类型列表", example = "[\"加氢站\", \"充电站\"]") + private List type; + + @Schema(description = "区域列表", example = "[\"华东\", \"华南\"]") + private List region; + + @Schema(description = "城市", example = "嘉兴市") + private String city; + + @Schema(description = "创建者", example = "admin") + private String creator; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/supplier/vo/SupplierRespVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/supplier/vo/SupplierRespVO.java new file mode 100644 index 0000000..a5d26f0 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/supplier/vo/SupplierRespVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.asset.controller.admin.supplier.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; + +/** + * 供应商信息 - 响应 VO + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - 供应商信息 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class SupplierRespVO extends SupplierBaseVO { + + @Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "创建者", example = "admin") + private String creator; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + + @Schema(description = "更新者", example = "admin") + private String updater; + + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime updateTime; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/supplier/vo/SupplierSaveReqVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/supplier/vo/SupplierSaveReqVO.java new file mode 100644 index 0000000..a094fa4 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/supplier/vo/SupplierSaveReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.asset.controller.admin.supplier.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +/** + * 供应商信息 - 创建/更新 Request VO + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - 供应商信息创建/更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class SupplierSaveReqVO extends SupplierBaseVO { + + @Schema(description = "主键ID", example = "1") + private Long id; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/supplier/SupplierConvert.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/supplier/SupplierConvert.java new file mode 100644 index 0000000..2bd7c62 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/supplier/SupplierConvert.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.asset.convert.supplier; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.asset.controller.admin.supplier.vo.SupplierRespVO; +import cn.iocoder.yudao.module.asset.controller.admin.supplier.vo.SupplierSaveReqVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.supplier.SupplierDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 供应商信息 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface SupplierConvert { + + SupplierConvert INSTANCE = Mappers.getMapper(SupplierConvert.class); + + SupplierDO convert(SupplierSaveReqVO bean); + + SupplierRespVO convert(SupplierDO bean); + + PageResult convertPage(PageResult page); + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/supplier/SupplierDO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/supplier/SupplierDO.java new file mode 100644 index 0000000..d69b9e9 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/supplier/SupplierDO.java @@ -0,0 +1,130 @@ +package cn.iocoder.yudao.module.asset.dal.dataobject.supplier; + +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.*; + +/** + * 供应商信息 DO + * + * @author 芋道源码 + */ +@TableName("asset_supplier") +@KeySequence("asset_supplier_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class SupplierDO extends BaseDO { + + /** + * 主键ID + */ + @TableId + private Long id; + + /** + * 供应商编码 + */ + private String supplierCode; + + /** + * 合作状态 + */ + private String coopStatus; + + /** + * 供应商名称 + */ + private String supplierName; + + /** + * 供应商类型 + */ + private String type; + + /** + * 省份 + */ + private String province; + + /** + * 城市 + */ + private String city; + + /** + * 详细地址 + */ + private String address; + + /** + * 区域 + */ + private String region; + + /** + * 联系人 + */ + private String contact; + + /** + * 联系手机 + */ + private String contactMobile; + + /** + * 联系电话 + */ + private String contactPhone; + + /** + * 邮箱 + */ + private String email; + + /** + * 统一社会信用代码/身份证号 + */ + private String creditCodeOrId; + + /** + * 备注 + */ + private String remark; + + /** + * 税号 + */ + private String taxId; + + /** + * 开票地址 + */ + private String invoiceAddress; + + /** + * 开票电话 + */ + private String invoicePhone; + + /** + * 账号 + */ + private String account; + + /** + * 开户行 + */ + private String openingBank; + + /** + * 邮寄地址 + */ + private String mailingAddress; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/supplier/SupplierMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/supplier/SupplierMapper.java new file mode 100644 index 0000000..8e93db7 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/supplier/SupplierMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.asset.dal.mysql.supplier; + +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.asset.controller.admin.supplier.vo.SupplierPageReqVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.supplier.SupplierDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 供应商信息 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface SupplierMapper extends BaseMapperX { + + default PageResult selectPage(SupplierPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(SupplierDO::getSupplierCode, reqVO.getSupplierCode()) + .inIfPresent(SupplierDO::getCoopStatus, reqVO.getCoopStatus()) + .likeIfPresent(SupplierDO::getSupplierName, reqVO.getSupplierName()) + .inIfPresent(SupplierDO::getType, reqVO.getType()) + .inIfPresent(SupplierDO::getRegion, reqVO.getRegion()) + .eqIfPresent(SupplierDO::getCity, reqVO.getCity()) + .eqIfPresent(SupplierDO::getCreator, reqVO.getCreator()) + .orderByDesc(SupplierDO::getId)); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/enums/ErrorCodeConstants.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/enums/ErrorCodeConstants.java index d3049b8..5b486d2 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/enums/ErrorCodeConstants.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/enums/ErrorCodeConstants.java @@ -20,4 +20,7 @@ public interface ErrorCodeConstants { // ========== 客户管理 1-008-003-000 ========== ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_008_003_000, "客户不存在"); + // ========== 供应商管理 1-008-004-000 ========== + ErrorCode SUPPLIER_NOT_EXISTS = new ErrorCode(1_008_004_000, "供应商不存在"); + } diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/supplier/SupplierService.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/supplier/SupplierService.java new file mode 100644 index 0000000..53273be --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/supplier/SupplierService.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.asset.service.supplier; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.asset.controller.admin.supplier.vo.SupplierPageReqVO; +import cn.iocoder.yudao.module.asset.controller.admin.supplier.vo.SupplierSaveReqVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.supplier.SupplierDO; + +import jakarta.validation.Valid; + +/** + * 供应商信息 Service 接口 + * + * @author 芋道源码 + */ +public interface SupplierService { + + /** + * 创建供应商 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createSupplier(@Valid SupplierSaveReqVO createReqVO); + + /** + * 更新供应商 + * + * @param updateReqVO 更新信息 + */ + void updateSupplier(@Valid SupplierSaveReqVO updateReqVO); + + /** + * 删除供应商 + * + * @param id 编号 + */ + void deleteSupplier(Long id); + + /** + * 获得供应商 + * + * @param id 编号 + * @return 供应商 + */ + SupplierDO getSupplier(Long id); + + /** + * 获得供应商分页 + * + * @param pageReqVO 分页查询 + * @return 供应商分页 + */ + PageResult getSupplierPage(SupplierPageReqVO pageReqVO); + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/supplier/SupplierServiceImpl.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/supplier/SupplierServiceImpl.java new file mode 100644 index 0000000..b1eb229 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/supplier/SupplierServiceImpl.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.module.asset.service.supplier; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.asset.controller.admin.supplier.vo.SupplierPageReqVO; +import cn.iocoder.yudao.module.asset.controller.admin.supplier.vo.SupplierSaveReqVO; +import cn.iocoder.yudao.module.asset.convert.supplier.SupplierConvert; +import cn.iocoder.yudao.module.asset.dal.dataobject.supplier.SupplierDO; +import cn.iocoder.yudao.module.asset.dal.mysql.supplier.SupplierMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import jakarta.annotation.Resource; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.asset.enums.ErrorCodeConstants.SUPPLIER_NOT_EXISTS; + +/** + * 供应商信息 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +@Slf4j +public class SupplierServiceImpl implements SupplierService { + + @Resource + private SupplierMapper supplierMapper; + + @Override + public Long createSupplier(SupplierSaveReqVO createReqVO) { + // 插入 + SupplierDO supplier = SupplierConvert.INSTANCE.convert(createReqVO); + supplierMapper.insert(supplier); + + log.info("[createSupplier][创建供应商成功,ID:{},供应商编码:{},供应商名称:{}]", + supplier.getId(), supplier.getSupplierCode(), supplier.getSupplierName()); + + return supplier.getId(); + } + + @Override + public void updateSupplier(SupplierSaveReqVO updateReqVO) { + // 校验存在 + validateSupplierExists(updateReqVO.getId()); + + // 更新 + SupplierDO updateObj = SupplierConvert.INSTANCE.convert(updateReqVO); + supplierMapper.updateById(updateObj); + + log.info("[updateSupplier][更新供应商成功,ID:{},供应商编码:{},供应商名称:{}]", + updateObj.getId(), updateObj.getSupplierCode(), updateObj.getSupplierName()); + } + + @Override + public void deleteSupplier(Long id) { + // 校验存在 + validateSupplierExists(id); + + // 删除 + supplierMapper.deleteById(id); + + log.info("[deleteSupplier][删除供应商成功,ID:{}]", id); + } + + private void validateSupplierExists(Long id) { + if (supplierMapper.selectById(id) == null) { + throw exception(SUPPLIER_NOT_EXISTS); + } + } + + @Override + public SupplierDO getSupplier(Long id) { + return supplierMapper.selectById(id); + } + + @Override + public PageResult getSupplierPage(SupplierPageReqVO pageReqVO) { + return supplierMapper.selectPage(pageReqVO); + } + +}