refactor: 优化资产模块字段和业务逻辑

- 添加 OCR 模块到主 pom.xml
- 优化客户管理模块
  - 调整客户字段(customerNo -> customerCode)
  - 新增合作状态、省份城市等字段
  - 新增客户商务经理关联表
  - 优化客户查询和保存逻辑
- 优化停车场管理
  - 调整停车场字段结构
  - 优化字段命名和注释
- 优化车型管理
  - 新增车型分类、能源类型等字段
  - 优化保养项目管理
  - 新增车型简化查询接口
- 新增数据库脚本
  - 车辆类型字典数据
  - 停车场和车型字段更新脚本
This commit is contained in:
kkfluous
2026-03-12 20:35:36 +08:00
parent 78a6cde22d
commit 30e15b90ea
23 changed files with 653 additions and 363 deletions

View File

@@ -18,6 +18,7 @@
<module>yudao-module-infra</module>
<module>yudao-module-bpm</module>
<module>yudao-module-asset</module>
<module>yudao-module-ocr</module>
</modules>
<name>${project.artifactId}</name>

View File

@@ -0,0 +1,85 @@
-- ==================== 车辆类型数据字典配置 ====================
-- 作者AI Assistant
-- 日期2026-03-12
-- 说明:为车型参数表的 vehicle_type 字段配置数据字典
-- ==================== 1. 创建车辆类型字典类型 ====================
INSERT INTO `system_dict_type` (
`name`,
`type`,
`status`,
`remark`,
`creator`,
`create_time`,
`updater`,
`update_time`,
`deleted`,
`deleted_time`
) VALUES (
'车辆类型',
'asset_vehicle_type',
0,
'车辆资产管理-车辆类型分类',
'admin',
NOW(),
'admin',
NOW(),
0,
NULL
);
-- ==================== 2. 创建车辆类型字典数据 ====================
-- 获取刚插入的字典类型ID
SET @dict_type_id = LAST_INSERT_ID();
INSERT INTO `system_dict_data` (
`sort`,
`label`,
`value`,
`dict_type`,
`status`,
`color_type`,
`css_class`,
`remark`,
`creator`,
`create_time`,
`updater`,
`update_time`,
`deleted`
) VALUES
(1, '小型轿车', '1', 'asset_vehicle_type', 0, 'primary', '', '5座以下的小型乘用车', 'admin', NOW(), 'admin', NOW(), 0),
(2, 'SUV', '2', 'asset_vehicle_type', 0, 'success', '', '运动型多用途车', 'admin', NOW(), 'admin', NOW(), 0),
(3, '厢式货车', '3', 'asset_vehicle_type', 0, 'info', '', '封闭式货运车辆', 'admin', NOW(), 'admin', NOW(), 0),
(4, '18吨双飞翼货车', '4', 'asset_vehicle_type', 0, 'warning', '', '大型货运车辆', 'admin', NOW(), 'admin', NOW(), 0),
(5, '轻型货车', '5', 'asset_vehicle_type', 0, 'default', '', '4.5吨以下货车', 'admin', NOW(), 'admin', NOW(), 0),
(6, '中型货车', '6', 'asset_vehicle_type', 0, 'default', '', '4.5-12吨货车', 'admin', NOW(), 'admin', NOW(), 0),
(7, '重型货车', '7', 'asset_vehicle_type', 0, 'danger', '', '12吨以上货车', 'admin', NOW(), 'admin', NOW(), 0),
(8, '客车', '8', 'asset_vehicle_type', 0, 'primary', '', '大中型客运车辆', 'admin', NOW(), 'admin', NOW(), 0),
(9, '专用车', '9', 'asset_vehicle_type', 0, 'info', '', '特种用途车辆', 'admin', NOW(), 'admin', NOW(), 0);
-- ==================== 3. 验证字典配置 ====================
SELECT
dt.name AS '字典类型',
dt.type AS '字典编码',
dd.label AS '字典标签',
dd.value AS '字典值',
dd.sort AS '排序',
dd.status AS '状态'
FROM system_dict_type dt
LEFT JOIN system_dict_data dd ON dt.type = dd.dict_type
WHERE dt.type = 'asset_vehicle_type'
ORDER BY dd.sort;
-- ==================== 4. 补充说明 ====================
-- 车牌颜色常用值(不需要字典,直接使用字符串):
-- - 绿牌:新能源车辆
-- - 蓝牌小型车辆9座以下
-- - 黄牌:大型车辆、货车、营运车辆
-- - 白牌:政府、军警用车
-- - 黑牌:外籍车辆、领事馆车辆
-- 电池类型常用值(不需要字典,直接使用字符串):
-- - 磷酸铁锂:安全性高,寿命长
-- - 三元锂:能量密度高
-- - 钛酸锂:快充性能好
-- - 固态电池:下一代电池技术

View File

@@ -0,0 +1,75 @@
-- ==================== 停车场和车型参数表字段补全 ====================
-- 作者AI Assistant
-- 日期2026-03-12
-- 说明:根据 AXURE 原型需求补全缺失字段
-- ==================== 1. 停车场表补全字段 ====================
-- 补全字段租金费用、合同文件URL
ALTER TABLE `asset_parking`
ADD COLUMN `rent_fee` decimal(10,2) DEFAULT NULL COMMENT '租金费用(元/月)' AFTER `remark`,
ADD COLUMN `contract_file_url` varchar(500) DEFAULT NULL COMMENT '合同文件URL' AFTER `rent_fee`;
-- 添加索引
ALTER TABLE `asset_parking`
ADD KEY `idx_lease_date` (`lease_start_date`, `lease_end_date`) COMMENT '租赁时间范围查询';
-- ==================== 2. 车型参数表补全字段 ====================
-- 补全字段:车辆类型、车牌颜色、电池类型、供氢系统厂家
ALTER TABLE `asset_vehicle_model`
ADD COLUMN `vehicle_type` int DEFAULT NULL COMMENT '车辆类型(字典)' AFTER `model`,
ADD COLUMN `plate_color` varchar(50) DEFAULT NULL COMMENT '车牌颜色(如:绿牌、蓝牌、黄牌)' AFTER `notice_model`,
ADD COLUMN `battery_type` varchar(100) DEFAULT NULL COMMENT '电池类型(如:磷酸铁锂、三元锂)' AFTER `battery_factory`,
ADD COLUMN `hydrogen_factory` varchar(200) DEFAULT NULL COMMENT '供氢系统厂家' AFTER `refrigerator_factory`;
-- 添加索引
ALTER TABLE `asset_vehicle_model`
ADD KEY `idx_vehicle_type` (`vehicle_type`) COMMENT '车辆类型查询',
ADD KEY `idx_brand_model` (`brand`, `model`) COMMENT '品牌型号组合查询';
-- ==================== 3. 数据字典补充说明 ====================
-- 以下字典需要在系统字典表中配置:
-- 车辆类型字典asset_vehicle_type
-- 示例值:
-- 1 - 小型轿车
-- 2 - SUV
-- 3 - 厢式货车
-- 4 - 18吨双飞翼货车
-- 车牌颜色常用值:
-- 绿牌(新能源车)
-- 蓝牌(小型车)
-- 黄牌(大型车、货车)
-- 白牌(政府、军警用车)
-- 黑牌(外籍车辆)
-- 电池类型常用值:
-- 磷酸铁锂
-- 三元锂
-- 钛酸锂
-- 固态电池
-- ==================== 4. 验证脚本 ====================
-- 验证停车场表字段
SELECT
COLUMN_NAME,
COLUMN_TYPE,
COLUMN_COMMENT
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'asset_parking'
AND COLUMN_NAME IN ('rent_fee', 'contract_file_url')
ORDER BY ORDINAL_POSITION;
-- 验证车型参数表字段
SELECT
COLUMN_NAME,
COLUMN_TYPE,
COLUMN_COMMENT
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'asset_vehicle_model'
AND COLUMN_NAME IN ('vehicle_type', 'plate_color', 'battery_type', 'hydrogen_factory')
ORDER BY ORDINAL_POSITION;

View File

@@ -12,16 +12,25 @@ import lombok.ToString;
@ToString(callSuper = true)
public class CustomerPageReqVO extends PageParam {
@Schema(description = "客户名称(模糊搜索)", example = "张三")
@Schema(description = "客户编号", example = "KH-2025-001")
private String customerCode;
@Schema(description = "客户名称(模糊搜索)", example = "嘉兴某某物流")
private String customerName;
@Schema(description = "联系电话(模糊搜索)", example = "13800138000")
private String contactPhone;
@Schema(description = "合作状态", example = "已合作")
private String coopStatus;
@Schema(description = "客户类型", example = "0")
private Integer customerType;
@Schema(description = "区域", example = "华东")
private String region;
@Schema(description = "状态", example = "0")
private Integer status;
@Schema(description = "省份", example = "浙江省")
private String province;
@Schema(description = "城市", example = "嘉兴市")
private String city;
@Schema(description = "联系人手机(模糊搜索)", example = "13800138000")
private String contactMobile;
}

View File

@@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.asset.controller.admin.customer.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 客户 Response VO")
@Data
@@ -13,67 +13,70 @@ public class CustomerRespVO {
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "CUST000001")
private String customerNo;
@Schema(description = "客户编号", example = "KH-2025-001")
private String customerCode;
@Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
@Schema(description = "合作状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "已合作")
private String coopStatus;
@Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "嘉兴某某物流有限公司")
private String customerName;
@Schema(description = "客户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
private Integer customerType;
@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 contactPerson;
private String contact;
@Schema(description = "联系电话", example = "13800138000")
@Schema(description = "联系人手机", example = "13800138000")
private String contactMobile;
@Schema(description = "联系人座机", example = "0571-88888888")
private String contactPhone;
@Schema(description = "联系邮箱", example = "zhangsan@example.com")
private String contactEmail;
@Schema(description = "电子邮箱", example = "zhangsan@example.com")
private String email;
@Schema(description = "联系地址", example = "上海市浦东新区")
private String contactAddress;
@Schema(description = "统一社会信用代码/身份证", example = "91330400MA2XXXXX1")
private String creditCodeOrId;
@Schema(description = "身份证号", example = "310101199001011234")
private String idCardNo;
@Schema(description = "身份证正面照片URL", example = "https://example.com/id_front.jpg")
private String idCardFrontUrl;
@Schema(description = "身份证反面照片URL", example = "https://example.com/id_back.jpg")
private String idCardBackUrl;
@Schema(description = "驾驶证号", example = "310101199001011234")
private String driverLicenseNo;
@Schema(description = "驾驶证照片URL", example = "https://example.com/driver_license.jpg")
private String driverLicenseUrl;
@Schema(description = "企业名称", example = "上海科技有限公司")
private String companyName;
@Schema(description = "统一社会信用代码", example = "91310000MA1FL0001A")
private String unifiedSocialCreditCode;
@Schema(description = "营业执照URL", example = "https://example.com/business_license.jpg")
private String businessLicenseUrl;
@Schema(description = "法人代表", example = "张总")
private String legalPerson;
@Schema(description = "信用等级", example = "1")
private Integer creditLevel;
@Schema(description = "押金金额", example = "5000.00")
private BigDecimal depositAmount;
@Schema(description = "业务负责人列表", example = "[\"张经理\", \"李专员\"]")
private List<String> businessManagers;
@Schema(description = "备注", example = "VIP客户")
private String remark;
@Schema(description = "状态", example = "0")
private Integer status;
@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;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
@Schema(description = "更新时间")
private LocalDateTime updateTime;
}

View File

@@ -3,15 +3,11 @@ package cn.iocoder.yudao.module.asset.controller.admin.customer.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
import java.math.BigDecimal;
import java.util.List;
@Schema(description = "管理后台 - 客户创建/更新 Request VO")
@Data
@@ -20,86 +16,88 @@ public class CustomerSaveReqVO {
@Schema(description = "主键ID更新时必填", example = "1")
private Long id;
@Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
@Schema(description = "客户编号", example = "KH-2025-001")
@Size(max = 50, message = "客户编号长度不能超过50个字符")
private String customerCode;
@Schema(description = "合作状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "已合作")
@NotBlank(message = "合作状态不能为空")
private String coopStatus;
@Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "嘉兴某某物流有限公司")
@NotBlank(message = "客户名称不能为空")
@Size(max = 100, message = "客户名称长度不能超过100个字符")
private String customerName;
@Schema(description = "客户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@NotNull(message = "客户类型不能为空")
@Min(value = 0, message = "客户类型值不正确")
@Max(value = 1, message = "客户类型值不正确")
private Integer customerType;
@Schema(description = "省份", example = "浙江省")
@Size(max = 50, message = "省份长度不能超过50个字符")
private String province;
@Schema(description = "联系人", example = "张三")
@Schema(description = "城市", example = "嘉兴市")
@Size(max = 50, message = "城市长度不能超过50个字符")
private String city;
@Schema(description = "地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "浙江省嘉兴市南湖区科技大道1号")
@NotBlank(message = "地址不能为空")
@Size(max = 255, message = "地址长度不能超过255个字符")
private String address;
@Schema(description = "区域", example = "华东")
@Size(max = 20, message = "区域长度不能超过20个字符")
private String region;
@Schema(description = "联系人", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
@NotBlank(message = "联系人不能为空")
@Size(max = 50, message = "联系人长度不能超过50个字符")
private String contactPerson;
private String contact;
@Schema(description = "联系电话", example = "13800138000")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "联系电话格式不正确")
@Schema(description = "联系人手机", requiredMode = Schema.RequiredMode.REQUIRED, example = "13800138000")
@NotBlank(message = "联系人手机不能为空")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "联系人手机格式不正确")
private String contactMobile;
@Schema(description = "联系人座机", example = "0571-88888888")
@Size(max = 20, message = "联系人座机长度不能超过20个字符")
private String contactPhone;
@Schema(description = "联系邮箱", example = "zhangsan@example.com")
@Email(message = "联系邮箱格式不正确")
@Size(max = 100, message = "联系邮箱长度不能超过100个字符")
private String contactEmail;
@Schema(description = "电子邮箱", example = "zhangsan@example.com")
@Email(message = "电子邮箱格式不正确")
@Size(max = 100, message = "电子邮箱长度不能超过100个字符")
private String email;
@Schema(description = "联系地址", example = "上海市浦东新区")
@Size(max = 255, message = "联系地址长度不能超过255个字符")
private String contactAddress;
@Schema(description = "统一社会信用代码/身份证", example = "91330400MA2XXXXX1")
@Size(max = 50, message = "统一社会信用代码/身份证长度不能超过50个字符")
private String creditCodeOrId;
@Schema(description = "身份证号", example = "310101199001011234")
@Pattern(regexp = "^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]$", message = "身份证号格式不正确")
private String idCardNo;
@Schema(description = "身份证正面照片URL", example = "https://example.com/id_front.jpg")
@Size(max = 255, message = "身份证正面照片URL长度不能超过255个字符")
private String idCardFrontUrl;
@Schema(description = "身份证反面照片URL", example = "https://example.com/id_back.jpg")
@Size(max = 255, message = "身份证反面照片URL长度不能超过255个字符")
private String idCardBackUrl;
@Schema(description = "驾驶证号", example = "310101199001011234")
@Size(max = 50, message = "驾驶证号长度不能超过50个字符")
private String driverLicenseNo;
@Schema(description = "驾驶证照片URL", example = "https://example.com/driver_license.jpg")
@Size(max = 255, message = "驾驶证照片URL长度不能超过255个字符")
private String driverLicenseUrl;
@Schema(description = "企业名称", example = "上海科技有限公司")
@Size(max = 200, message = "企业名称长度不能超过200个字符")
private String companyName;
@Schema(description = "统一社会信用代码", example = "91310000MA1FL0001A")
@Pattern(regexp = "^[0-9A-HJ-NPQRTUWXY]{2}\\d{6}[0-9A-HJ-NPQRTUWXY]{10}$", message = "统一社会信用代码格式不正确")
private String unifiedSocialCreditCode;
@Schema(description = "营业执照URL", example = "https://example.com/business_license.jpg")
@Size(max = 255, message = "营业执照URL长度不能超过255个字符")
private String businessLicenseUrl;
@Schema(description = "法人代表", example = "张总")
@Size(max = 50, message = "法人代表长度不能超过50个字符")
private String legalPerson;
@Schema(description = "信用等级", example = "1")
@Min(value = 0, message = "信用等级值不正确")
@Max(value = 4, message = "信用等级值不正确")
private Integer creditLevel;
@Schema(description = "押金金额", example = "5000.00")
@DecimalMin(value = "0.00", message = "押金金额不能为负数")
private BigDecimal depositAmount;
@Schema(description = "业务负责人列表", example = "[\"张经理\", \"李专员\"]")
private List<String> businessManagers;
@Schema(description = "备注", example = "VIP客户")
@Size(max = 500, message = "备注长度不能超过500个字符")
private String remark;
@Schema(description = "状态", example = "0")
@Min(value = 0, message = "状态值不正确")
@Max(value = 2, message = "状态值不正确")
private Integer status;
@Schema(description = "纳税人识别号", example = "91330400MA2XXXXX1")
@Size(max = 50, message = "纳税人识别号长度不能超过50个字符")
private String taxId;
@Schema(description = "发票地址", example = "浙江省嘉兴市南湖区科技大道1号")
@Size(max = 255, message = "发票地址长度不能超过255个字符")
private String invoiceAddress;
@Schema(description = "发票电话", example = "0571-88888888")
@Size(max = 20, message = "发票电话长度不能超过20个字符")
private String invoicePhone;
@Schema(description = "银行账号", example = "6222021234567890123")
@Size(max = 50, message = "银行账号长度不能超过50个字符")
private String account;
@Schema(description = "开户行", example = "中国工商银行嘉兴分行")
@Size(max = 100, message = "开户行长度不能超过100个字符")
private String openingBank;
@Schema(description = "邮寄地址", example = "浙江省嘉兴市南湖区科技大道1号")
@Size(max = 255, message = "邮寄地址长度不能超过255个字符")
private String mailingAddress;
}

View File

@@ -53,19 +53,10 @@ public class ParkingBaseVO {
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String contactPhone;
@Schema(description = "公司负责人", example = "王五")
private String principal;
@Schema(description = "已停车辆数", example = "50")
@Min(value = 0, message = "已停车辆数不能为负数")
private Integer parkedAmount;
@Schema(description = "库存区域(字典)", example = "1")
private Integer stockArea;
@Schema(description = "异动城市(字典)", example = "1")
private Integer unusualActionCity;
@Schema(description = "经度", example = "120.123456")
@Pattern(regexp = "^-?((0|[1-9]\\d?|1[0-7]\\d)(\\.\\d{1,6})?|180(\\.0{1,6})?)$", message = "经度格式不正确,范围:-180~180")
private String longitude;
@@ -74,7 +65,11 @@ public class ParkingBaseVO {
@Pattern(regexp = "^-?((0|[1-8]?\\d)(\\.\\d{1,6})?|90(\\.0{1,6})?)$", message = "纬度格式不正确,范围:-90~90")
private String latitude;
@Schema(description = "备注", example = "备注信息")
private String remark;
@Schema(description = "租金费用(元/月)", example = "5000.00")
@Min(value = 0, message = "租金费用不能为负数")
private java.math.BigDecimal rentFee;
@Schema(description = "合同文件URL", example = "https://example.com/contract.pdf")
private String contractFileUrl;
}

View File

@@ -91,7 +91,7 @@ public class VehicleModelController {
@GetMapping("/list-by-brand")
@Operation(summary = "根据品牌获取车型参数列表")
@Parameter(name = "brand", description = "品牌", required = true)
public CommonResult<List<VehicleModelRespVO>> getVehicleModelListByBrand(@RequestParam("brand") Integer brand) {
public CommonResult<List<VehicleModelRespVO>> getVehicleModelListByBrand(@RequestParam("brand") String brand) {
List<VehicleModelDO> list = vehicleModelService.getVehicleModelListByBrand(brand);
return success(BeanUtils.toBean(list, VehicleModelRespVO.class));
}
@@ -99,7 +99,7 @@ public class VehicleModelController {
@GetMapping("/list-by-model")
@Operation(summary = "根据车型获取车型参数列表")
@Parameter(name = "model", description = "车型", required = true)
public CommonResult<List<VehicleModelRespVO>> getVehicleModelListByModel(@RequestParam("model") Integer model) {
public CommonResult<List<VehicleModelRespVO>> getVehicleModelListByModel(@RequestParam("model") String model) {
List<VehicleModelDO> list = vehicleModelService.getVehicleModelListByModel(model);
return success(BeanUtils.toBean(list, VehicleModelRespVO.class));
}

View File

@@ -17,45 +17,38 @@ import java.math.BigDecimal;
@Data
public class VehicleModelBaseVO {
@Schema(description = "品牌(字典)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "品牌不能为空")
private Integer brand;
@Schema(description = "品牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "帕力安牌")
@NotBlank(message = "品牌不能为空")
private String brand;
@Schema(description = "车型(字典)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "型不能为空")
private Integer model;
@Schema(description = "型号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XDQ504LXCFCEV01")
@NotBlank(message = "不能为空")
private String model;
@Schema(description = "车型编号", example = "HFC1043K1")
private String modelCode;
@Schema(description = "型号label", example = "4.5T冷链车")
private String modelLabel;
@Schema(description = "车型名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "江淮骏铃V6")
@NotBlank(message = "车型名称不能为空")
private String modelName;
@Schema(description = "车辆公告型号", example = "HFC1043K1R8T")
private String noticeModel;
@Schema(description = "仪表盘氢气单位(字典)", example = "1")
private Integer hydrogenUnit;
@Schema(description = "仪表盘氢气单位", example = "%、MPa、Kg")
private String hydrogenUnit;
@Schema(description = "氢瓶容量(L)", example = "165")
@Min(value = 0, message = "氢瓶容量不能为负数")
private Integer hydrogenCapacity;
@Schema(description = "池公告可行驶里程(KM)", example = "300")
@Min(value = 0, message = "池公告可行驶里程不能为负数")
@Schema(description = "续航里程(KM)", example = "300")
@Min(value = 0, message = "续航里程不能为负数")
private Integer electricityMileage;
@Schema(description = "储电量(kwh)", example = "80.00")
@DecimalMin(value = "0.0", message = "储电量不能为负数")
private BigDecimal reserveElectricity;
@Schema(description = "气公告可行驶里程(KM)", example = "400")
@Min(value = 0, message = "气公告可行驶里程不能为负数")
@Schema(description = "续航里程(KM)", example = "400")
@Min(value = 0, message = "续航里程不能为负数")
private Integer hydrogenMileage;
@Schema(description = "燃料种类(字典)", example = "1")
private Integer fuelType;
@Schema(description = "燃料种类", example = "氢、电、柴油")
private String fuelType;
@Schema(description = "轮胎尺寸", example = "225/70R19.5")
private String tireSize;
@@ -64,8 +57,14 @@ public class VehicleModelBaseVO {
@Min(value = 1, message = "轮胎数量必须大于0")
private Integer tireNumber;
@Schema(description = "车辆尺寸", example = "5995×2100×2850")
private String truckSize;
@Schema(description = "车辆尺寸_长", example = "5995")
private String truckSize_x;
@Schema(description = "车辆尺寸_宽", example = "2260")
private String truckSize_y;
@Schema(description = "车辆尺寸_高", example = "3320")
private String truckSize_z;
@Schema(description = "电堆厂家", example = "上海重塑")
private String onlineSpreadEnterprise;
@@ -76,4 +75,16 @@ public class VehicleModelBaseVO {
@Schema(description = "冷机厂家", example = "开山")
private String refrigeratorFactory;
@Schema(description = "车辆类型", example = "轻型箱式货车")
private String vehicleType;
@Schema(description = "车牌颜色", example = "绿牌")
private String plateColor;
@Schema(description = "电池类型", example = "磷酸铁锂")
private String batteryType;
@Schema(description = "供氢系统厂家", example = "北京亿华通")
private String hydrogenFactory;
}

View File

@@ -24,17 +24,17 @@ public class VehicleModelMaintainItemVO {
@NotBlank(message = "保养项目不能为空")
private String maintainItem;
@Schema(description = "保养内容", example = "更换机油、机滤")
private String maintainContent;
@Schema(description = "材料费", example = "200.00")
@Schema(description = "材料费(元)", example = "200.00")
@DecimalMin(value = "0.0", message = "材料费不能为负数")
private BigDecimal materialsExpenses;
private BigDecimal materialFee;
@Schema(description = "工时费", example = "100.00")
@Schema(description = "工时费(元)", example = "100.00")
@DecimalMin(value = "0.0", message = "工时费不能为负数")
private BigDecimal hourFee;
@Schema(description = "费用合计(元)", example = "300.00")
private BigDecimal totalFee;
@Schema(description = "保养公里周期(KM)", example = "5000")
@Min(value = 1, message = "保养公里周期必须大于0")
private Integer kilometerCycle;

View File

@@ -17,19 +17,13 @@ import lombok.ToString;
@ToString(callSuper = true)
public class VehicleModelPageReqVO extends PageParam {
@Schema(description = "品牌(字典)", example = "1")
private Integer brand;
@Schema(description = "品牌", example = "帕力安牌")
private String brand;
@Schema(description = "车型(字典)", example = "1")
private Integer model;
@Schema(description = "型号", example = "XDQ504LXCFCEV01")
private String model;
@Schema(description = "车型名称", example = "江淮骏铃V6")
private String modelName;
@Schema(description = "车型编号", example = "HFC1043K1")
private String modelCode;
@Schema(description = "燃料种类(字典)", example = "1")
private Integer fuelType;
@Schema(description = "燃料种类", example = "氢、电、柴油")
private String fuelType;
}

View File

@@ -15,13 +15,13 @@ public class VehicleModelSimpleRespVO {
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "车型名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "江淮骏铃V6")
private String modelName;
@Schema(description = "品牌", example = "帕力安牌")
private String brand;
@Schema(description = "品牌(字典)", example = "1")
private Integer brand;
@Schema(description = "型号", example = "XDQ504LXCFCEV01")
private String model;
@Schema(description = "车型(字典)", example = "1")
private Integer model;
@Schema(description = "型号label", example = "4.5T冷链车")
private String modelLabel;
}

View File

@@ -0,0 +1,40 @@
package cn.iocoder.yudao.module.asset.dal.dataobject.customer;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* 客户业务负责人关联 DO
*
* @author 芋道源码
*/
@TableName("asset_customer_business_manager")
@KeySequence("asset_customer_business_manager_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CustomerBusinessManagerDO extends BaseDO {
/**
* 主键ID
*/
@TableId
private Long id;
/**
* 客户ID
*/
private Long customerId;
/**
* 业务负责人姓名
*/
private String businessManagerName;
}

View File

@@ -6,8 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import java.math.BigDecimal;
/**
* 客户信息 DO
*
@@ -32,7 +30,12 @@ public class CustomerDO extends BaseDO {
/**
* 客户编号
*/
private String customerNo;
private String customerCode;
/**
* 合作状态
*/
private String coopStatus;
/**
* 客户名称
@@ -40,84 +43,49 @@ public class CustomerDO extends BaseDO {
private String customerName;
/**
* 客户类型0=个人 1=企业)
* 省份
*/
private Integer customerType;
private String province;
/**
* 城市
*/
private String city;
/**
* 地址
*/
private String address;
/**
* 区域
*/
private String region;
/**
* 联系人
*/
private String contactPerson;
private String contact;
/**
* 联系电话
* 联系人手机
*/
private String contactMobile;
/**
* 联系人座机
*/
private String contactPhone;
/**
* 联系邮箱
* 电子邮箱
*/
private String contactEmail;
private String email;
/**
* 联系地址
* 统一社会信用代码/身份证
*/
private String contactAddress;
/**
* 身份证号
*/
private String idCardNo;
/**
* 身份证正面照片URL
*/
private String idCardFrontUrl;
/**
* 身份证反面照片URL
*/
private String idCardBackUrl;
/**
* 驾驶证号
*/
private String driverLicenseNo;
/**
* 驾驶证照片URL
*/
private String driverLicenseUrl;
/**
* 企业名称
*/
private String companyName;
/**
* 统一社会信用代码
*/
private String unifiedSocialCreditCode;
/**
* 营业执照URL
*/
private String businessLicenseUrl;
/**
* 法人代表
*/
private String legalPerson;
/**
* 信用等级0=未评级 1=A级 2=B级 3=C级 4=D级
*/
private Integer creditLevel;
/**
* 押金金额
*/
private BigDecimal depositAmount;
private String creditCodeOrId;
/**
* 备注
@@ -125,8 +93,33 @@ public class CustomerDO extends BaseDO {
private String remark;
/**
* 状态0=正常 1=冻结 2=黑名单)
* 纳税人识别号
*/
private Integer status;
private String taxId;
/**
* 发票地址
*/
private String invoiceAddress;
/**
* 发票电话
*/
private String invoicePhone;
/**
* 银行账号
*/
private String account;
/**
* 开户行
*/
private String openingBank;
/**
* 邮寄地址
*/
private String mailingAddress;
}

View File

@@ -28,42 +28,16 @@ public class ParkingDO extends BaseDO {
*/
@TableId
private Long id;
/**
* 停车场名称
*/
private String name;
/**
* 地址
*/
private String address;
/**
* 容量
*/
private Integer capacity;
/**
* 省份
*/
private String province;
/**
* 城市
*/
private String city;
/**
* 租赁开始时间
*/
private LocalDate leaseStartDate;
/**
* 租赁结束时间
*/
private LocalDate leaseEndDate;
/**
* 负责人
*/
@@ -84,25 +58,25 @@ public class ParkingDO extends BaseDO {
*/
private String contactPhone;
/**
* 公司负责人
*/
private String principal;
/**
* 已停车辆数
*/
private Integer parkedAmount;
/**
* 库存区域(字典)
* 省份
*/
private Integer stockArea;
private String province;
/**
* 异动城市(字典)
* 城市
*/
private Integer unusualActionCity;
private String city;
/**
* 地址
*/
private String address;
/**
* 经度
@@ -115,8 +89,23 @@ public class ParkingDO extends BaseDO {
private String latitude;
/**
* 备注
* 租赁开始时间
*/
private String remark;
private LocalDate leaseStartDate;
/**
* 租赁结束时间
*/
private LocalDate leaseEndDate;
/**
* 租金费用(元/月)
*/
private java.math.BigDecimal rentFee;
/**
* 合同文件URL
*/
private String contractFileUrl;
}

View File

@@ -30,88 +30,107 @@ public class VehicleModelDO extends BaseDO {
private Long id;
/**
* 品牌(字典)
* 品牌:帕力安牌
*/
private Integer brand;
private String brand;
/**
* 车型(字典)
* 型号XDQ504LXCFCEV01
*/
private Integer model;
private String model;
/**
* 车型编号
* 车辆类型:轻型箱式货车
*/
private String modelCode;
private String vehicleType;
/**
* 车型名称
* 型号label4.5T冷链
*/
private String modelName;
private String modelLabel;
/**
* 车辆公告型号
* 燃料种类:氢、电、柴油
*/
private String noticeModel;
private String fuelType;
/**
* 仪表盘氢气单位(字典)
* 车牌颜色::绿牌、黄牌、黄绿牌
*/
private Integer hydrogenUnit;
private String plateColor;
/**
* 氢瓶容量(L)
* 车辆尺寸_长 5995
*/
private Integer hydrogenCapacity;
private String truckSize_x;
/**
* 电池公告可行驶里程(KM)
* 车辆尺寸_宽2260
*/
private Integer electricityMileage;
private String truckSize_y;
/**
* 储电量(kwh)
* 车辆尺寸_高3320
*/
private BigDecimal reserveElectricity;
private String truckSize_z;
/**
* 氢气公告可行驶里程(KM)
*/
private Integer hydrogenMileage;
/**
* 燃料种类(字典)
*/
private Integer fuelType;
/**
* 轮胎尺寸
* 轮胎规格7.00T6LT0PT
*/
private String tireSize;
/**
* 轮胎数量
* 轮胎数量6
*/
private Integer tireNumber;
/**
* 车辆尺寸
* 电池类型:磷酸铁锂、三元锂
*/
private String truckSize;
/**
* 电堆厂家
*/
private String onlineSpreadEnterprise;
private String batteryType;
/**
* 电池厂家
*/
private String batteryFactory;
/**
* 储电量(kwh)
*/
private BigDecimal reserveElectricity;
/**
* 电续航里程(KM)
*/
private Integer electricityMileage;
/**
* 氢瓶容量(L)
*/
private Integer hydrogenCapacity;
/**
* 供氢系统厂家
*/
private String hydrogenFactory;
/**
* 仪表盘氢气单位: %、MPa、Kg
*/
private String hydrogenUnit;
/**
* 氢续航里程(KM)
*/
private Integer hydrogenMileage;
/**
* 冷机厂家
*/
private String refrigeratorFactory;
/**
* 电堆厂家
*/
private String onlineSpreadEnterprise;
}

View File

@@ -39,21 +39,6 @@ public class VehicleModelMaintainItemDO extends BaseDO {
*/
private String maintainItem;
/**
* 保养内容
*/
private String maintainContent;
/**
* 材料费
*/
private BigDecimal materialsExpenses;
/**
* 工时费
*/
private BigDecimal hourFee;
/**
* 保养公里周期(KM)
*/
@@ -64,4 +49,18 @@ public class VehicleModelMaintainItemDO extends BaseDO {
*/
private Integer timeCycle;
/**
* 工时费(元)
*/
private BigDecimal hourFee;
/**
* 材料费(元)
*/
private BigDecimal materialFee;
/**
* 费用合计(元)
*/
private BigDecimal totalFee;
}

View File

@@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.asset.dal.mysql.customer;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.asset.dal.dataobject.customer.CustomerBusinessManagerDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 客户业务负责人关联 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface CustomerBusinessManagerMapper extends BaseMapperX<CustomerBusinessManagerDO> {
/**
* 根据客户ID查询业务负责人列表
*/
default List<CustomerBusinessManagerDO> selectListByCustomerId(Long customerId) {
return selectList(CustomerBusinessManagerDO::getCustomerId, customerId);
}
/**
* 根据客户ID删除业务负责人
*/
default void deleteByCustomerId(Long customerId) {
delete(CustomerBusinessManagerDO::getCustomerId, customerId);
}
}

View File

@@ -17,10 +17,13 @@ public interface CustomerMapper extends BaseMapperX<CustomerDO> {
default PageResult<CustomerDO> selectPage(CustomerPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<CustomerDO>()
.eqIfPresent(CustomerDO::getCustomerCode, reqVO.getCustomerCode())
.likeIfPresent(CustomerDO::getCustomerName, reqVO.getCustomerName())
.likeIfPresent(CustomerDO::getContactPhone, reqVO.getContactPhone())
.eqIfPresent(CustomerDO::getCustomerType, reqVO.getCustomerType())
.eqIfPresent(CustomerDO::getStatus, reqVO.getStatus())
.eqIfPresent(CustomerDO::getCoopStatus, reqVO.getCoopStatus())
.eqIfPresent(CustomerDO::getRegion, reqVO.getRegion())
.eqIfPresent(CustomerDO::getProvince, reqVO.getProvince())
.eqIfPresent(CustomerDO::getCity, reqVO.getCity())
.likeIfPresent(CustomerDO::getContactMobile, reqVO.getContactMobile())
.orderByDesc(CustomerDO::getId));
}

View File

@@ -21,17 +21,15 @@ public interface VehicleModelMapper extends BaseMapperX<VehicleModelDO> {
return selectPage(reqVO, new LambdaQueryWrapperX<VehicleModelDO>()
.eqIfPresent(VehicleModelDO::getBrand, reqVO.getBrand())
.eqIfPresent(VehicleModelDO::getModel, reqVO.getModel())
.likeIfPresent(VehicleModelDO::getModelName, reqVO.getModelName())
.likeIfPresent(VehicleModelDO::getModelCode, reqVO.getModelCode())
.eqIfPresent(VehicleModelDO::getFuelType, reqVO.getFuelType())
.orderByDesc(VehicleModelDO::getId));
}
default List<VehicleModelDO> selectListByBrand(Integer brand) {
default List<VehicleModelDO> selectListByBrand(String brand) {
return selectList(VehicleModelDO::getBrand, brand);
}
default List<VehicleModelDO> selectListByModel(Integer model) {
default List<VehicleModelDO> selectListByModel(String model) {
return selectList(VehicleModelDO::getModel, model);
}

View File

@@ -4,13 +4,17 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.asset.controller.admin.customer.vo.CustomerPageReqVO;
import cn.iocoder.yudao.module.asset.controller.admin.customer.vo.CustomerSaveReqVO;
import cn.iocoder.yudao.module.asset.convert.customer.CustomerConvert;
import cn.iocoder.yudao.module.asset.dal.dataobject.customer.CustomerBusinessManagerDO;
import cn.iocoder.yudao.module.asset.dal.dataobject.customer.CustomerDO;
import cn.iocoder.yudao.module.asset.dal.mysql.customer.CustomerBusinessManagerMapper;
import cn.iocoder.yudao.module.asset.dal.mysql.customer.CustomerMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.asset.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS;
@@ -28,36 +32,53 @@ public class CustomerServiceImpl implements CustomerService {
@Resource
private CustomerMapper customerMapper;
@Resource
private CustomerBusinessManagerMapper customerBusinessManagerMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public Long createCustomer(CustomerSaveReqVO createReqVO) {
// 转换并插入
CustomerDO customer = CustomerConvert.INSTANCE.convert(createReqVO);
// 生成客户编号
if (customer.getCustomerNo() == null) {
customer.setCustomerNo(generateCustomerNo());
if (customer.getCustomerCode() == null) {
customer.setCustomerCode(generateCustomerCode());
}
customerMapper.insert(customer);
// 保存业务负责人
saveBusinessManagers(customer.getId(), createReqVO.getBusinessManagers());
return customer.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateCustomer(CustomerSaveReqVO updateReqVO) {
// 校验存在
validateCustomerExists(updateReqVO.getId());
// 转换并更新
CustomerDO updateObj = CustomerConvert.INSTANCE.convert(updateReqVO);
customerMapper.updateById(updateObj);
// 更新业务负责人:先删除旧的,再插入新的
customerBusinessManagerMapper.deleteByCustomerId(updateReqVO.getId());
saveBusinessManagers(updateReqVO.getId(), updateReqVO.getBusinessManagers());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteCustomer(Long id) {
// 校验存在
validateCustomerExists(id);
// 删除
// 删除业务负责人
customerBusinessManagerMapper.deleteByCustomerId(id);
// 删除客户
customerMapper.deleteById(id);
}
@@ -80,10 +101,29 @@ public class CustomerServiceImpl implements CustomerService {
/**
* 生成客户编号
*/
private String generateCustomerNo() {
private String generateCustomerCode() {
// 查询最大ID
Long maxId = customerMapper.selectCount();
return String.format("CUST%06d", maxId + 1);
return String.format("KH-%04d-%03d", java.time.Year.now().getValue(), maxId + 1);
}
/**
* 保存业务负责人
*/
private void saveBusinessManagers(Long customerId, List<String> businessManagers) {
if (businessManagers == null || businessManagers.isEmpty()) {
return;
}
for (String managerName : businessManagers) {
if (managerName != null && !managerName.trim().isEmpty()) {
CustomerBusinessManagerDO managerDO = CustomerBusinessManagerDO.builder()
.customerId(customerId)
.businessManagerName(managerName.trim())
.build();
customerBusinessManagerMapper.insert(managerDO);
}
}
}
}

View File

@@ -67,7 +67,7 @@ public interface VehicleModelService {
* @param brand 品牌
* @return 车型参数列表
*/
List<VehicleModelDO> getVehicleModelListByBrand(Integer brand);
List<VehicleModelDO> getVehicleModelListByBrand(String brand);
/**
* 根据车型获取车型参数列表
@@ -75,7 +75,7 @@ public interface VehicleModelService {
* @param model 车型
* @return 车型参数列表
*/
List<VehicleModelDO> getVehicleModelListByModel(Integer model);
List<VehicleModelDO> getVehicleModelListByModel(String model);
/**
* 获取车型的维保项目列表

View File

@@ -14,6 +14,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.math.BigDecimal;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -100,12 +101,12 @@ public class VehicleModelServiceImpl implements VehicleModelService {
}
@Override
public List<VehicleModelDO> getVehicleModelListByBrand(Integer brand) {
public List<VehicleModelDO> getVehicleModelListByBrand(String brand) {
return vehicleModelMapper.selectListByBrand(brand);
}
@Override
public List<VehicleModelDO> getVehicleModelListByModel(Integer model) {
public List<VehicleModelDO> getVehicleModelListByModel(String model) {
return vehicleModelMapper.selectListByModel(model);
}
@@ -126,10 +127,16 @@ public class VehicleModelServiceImpl implements VehicleModelService {
if (maintainItems == null || maintainItems.isEmpty()) {
return;
}
for (VehicleModelMaintainItemVO item : maintainItems) {
VehicleModelMaintainItemDO maintainItem = BeanUtils.toBean(item, VehicleModelMaintainItemDO.class);
maintainItem.setVehicleModelId(vehicleModelId);
// 自动计算 totalFee处理 null 值
BigDecimal hourFee = item.getHourFee() != null ? item.getHourFee() : BigDecimal.ZERO;
BigDecimal materialFee = item.getMaterialFee() != null ? item.getMaterialFee() : BigDecimal.ZERO;
maintainItem.setTotalFee(hourFee.add(materialFee));
vehicleModelMaintainItemMapper.insert(maintainItem);
}
}