From 0706b51acd1ae10e4aaa958d11e449bb1745ad51 Mon Sep 17 00:00:00 2001 From: kkfluous Date: Thu, 12 Mar 2026 14:45:51 +0800 Subject: [PATCH] =?UTF-8?q?feat(asset):=20=E5=AE=A2=E6=88=B7=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E6=A8=A1=E5=9D=97=E5=BC=80=E5=8F=91=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增客户管理 CRUD 功能(个人/企业客户) - 新增 7 个单元测试用例(全部通过) - 新增测试配置和 SQL 脚本 - 车辆管理字段补充(32个新字段) - ECS 部署测试通过 --- .../admin/customer/CustomerController.java | 78 ++++++ .../admin/customer/vo/CustomerPageReqVO.java | 27 +++ .../admin/customer/vo/CustomerRespVO.java | 79 ++++++ .../admin/customer/vo/CustomerSaveReqVO.java | 105 ++++++++ .../admin/vehicle/vo/VehicleRespVO.java | 109 +++++++-- .../convert/customer/CustomerConvert.java | 26 ++ .../asset/convert/vehicle/VehicleConvert.java | 24 ++ .../dal/dataobject/customer/CustomerDO.java | 132 ++++++++++ .../dal/dataobject/vehicle/VehicleBaseDO.java | 30 +++ .../dataobject/vehicle/VehicleBusinessDO.java | 15 ++ .../dataobject/vehicle/VehicleLocationDO.java | 25 ++ .../dataobject/vehicle/VehicleStatusDO.java | 50 ++++ .../dal/mysql/customer/CustomerMapper.java | 27 +++ .../asset/enums/ErrorCodeConstants.java | 3 + .../service/customer/CustomerService.java | 55 +++++ .../service/customer/CustomerServiceImpl.java | 89 +++++++ .../customer/CustomerServiceImplTest.java | 228 ++++++++++++++++++ .../test/resources/application-unit-test.yaml | 25 ++ .../src/test/resources/sql/clean.sql | 2 + .../src/test/resources/sql/create_tables.sql | 30 +++ 20 files changed, 1140 insertions(+), 19 deletions(-) create mode 100644 yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/customer/CustomerController.java create mode 100644 yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/customer/vo/CustomerPageReqVO.java create mode 100644 yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/customer/vo/CustomerRespVO.java create mode 100644 yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/customer/vo/CustomerSaveReqVO.java create mode 100644 yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/customer/CustomerConvert.java create mode 100644 yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/customer/CustomerDO.java create mode 100644 yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/customer/CustomerMapper.java create mode 100644 yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/customer/CustomerService.java create mode 100644 yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/customer/CustomerServiceImpl.java create mode 100644 yudao-module-asset/yudao-module-asset-server/src/test/java/cn/iocoder/yudao/module/asset/service/customer/CustomerServiceImplTest.java create mode 100644 yudao-module-asset/yudao-module-asset-server/src/test/resources/application-unit-test.yaml create mode 100644 yudao-module-asset/yudao-module-asset-server/src/test/resources/sql/clean.sql create mode 100644 yudao-module-asset/yudao-module-asset-server/src/test/resources/sql/create_tables.sql diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/customer/CustomerController.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/customer/CustomerController.java new file mode 100644 index 0000000..7bdcf7e --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/customer/CustomerController.java @@ -0,0 +1,78 @@ +package cn.iocoder.yudao.module.asset.controller.admin.customer; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +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.CustomerRespVO; +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.CustomerDO; +import cn.iocoder.yudao.module.asset.service.customer.CustomerService; +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/customer") +@Validated +public class CustomerController { + + @Resource + private CustomerService customerService; + + @PostMapping("/create") + @Operation(summary = "创建客户") + @PreAuthorize("@ss.hasPermission('asset:customer:create')") + public CommonResult createCustomer(@Valid @RequestBody CustomerSaveReqVO createReqVO) { + return success(customerService.createCustomer(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新客户") + @PreAuthorize("@ss.hasPermission('asset:customer:update')") + public CommonResult updateCustomer(@Valid @RequestBody CustomerSaveReqVO updateReqVO) { + customerService.updateCustomer(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除客户") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('asset: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 = "1") + @PreAuthorize("@ss.hasPermission('asset:customer:query')") + public CommonResult getCustomer(@RequestParam("id") Long id) { + CustomerDO customer = customerService.getCustomer(id); + return success(CustomerConvert.INSTANCE.convert(customer)); + } + + @GetMapping("/page") + @Operation(summary = "获得客户分页") + @PreAuthorize("@ss.hasPermission('asset:customer:query')") + public CommonResult> getCustomerPage(@Valid CustomerPageReqVO pageReqVO) { + PageResult pageResult = customerService.getCustomerPage(pageReqVO); + return success(CustomerConvert.INSTANCE.convertPage(pageResult)); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/customer/vo/CustomerPageReqVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/customer/vo/CustomerPageReqVO.java new file mode 100644 index 0000000..78aa50a --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/customer/vo/CustomerPageReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.asset.controller.admin.customer.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - 客户分页查询 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CustomerPageReqVO extends PageParam { + + @Schema(description = "客户名称(模糊搜索)", example = "张三") + private String customerName; + + @Schema(description = "联系电话(模糊搜索)", example = "13800138000") + private String contactPhone; + + @Schema(description = "客户类型", example = "0") + private Integer customerType; + + @Schema(description = "状态", example = "0") + private Integer status; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/customer/vo/CustomerRespVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/customer/vo/CustomerRespVO.java new file mode 100644 index 0000000..06e40b3 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/customer/vo/CustomerRespVO.java @@ -0,0 +1,79 @@ +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; + +@Schema(description = "管理后台 - 客户 Response VO") +@Data +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 = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + private String customerName; + + @Schema(description = "客户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + private Integer customerType; + + @Schema(description = "联系人", example = "张三") + private String contactPerson; + + @Schema(description = "联系电话", example = "13800138000") + private String contactPhone; + + @Schema(description = "联系邮箱", example = "zhangsan@example.com") + private String contactEmail; + + @Schema(description = "联系地址", example = "上海市浦东新区") + private String contactAddress; + + @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 = "VIP客户") + private String remark; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/customer/vo/CustomerSaveReqVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/customer/vo/CustomerSaveReqVO.java new file mode 100644 index 0000000..6df2fa2 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/customer/vo/CustomerSaveReqVO.java @@ -0,0 +1,105 @@ +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; + +@Schema(description = "管理后台 - 客户创建/更新 Request VO") +@Data +public class CustomerSaveReqVO { + + @Schema(description = "主键ID(更新时必填)", example = "1") + private Long id; + + @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 contactPerson; + + @Schema(description = "联系电话", example = "13800138000") + @Pattern(regexp = "^1[3-9]\\d{9}$", message = "联系电话格式不正确") + private String contactPhone; + + @Schema(description = "联系邮箱", example = "zhangsan@example.com") + @Email(message = "联系邮箱格式不正确") + @Size(max = 100, message = "联系邮箱长度不能超过100个字符") + private String contactEmail; + + @Schema(description = "联系地址", example = "上海市浦东新区") + @Size(max = 255, message = "联系地址长度不能超过255个字符") + private String contactAddress; + + @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 = "VIP客户") + @Size(max = 500, message = "备注长度不能超过500个字符") + private String remark; + + @Schema(description = "状态", example = "0") + @Min(value = 0, message = "状态值不正确") + @Max(value = 2, message = "状态值不正确") + private Integer status; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/vehicle/vo/VehicleRespVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/vehicle/vo/VehicleRespVO.java index 02b73f0..e01a1af 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/vehicle/vo/VehicleRespVO.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/vehicle/vo/VehicleRespVO.java @@ -14,16 +14,25 @@ public class VehicleRespVO { @Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long id; - // ==================== 基础信息(asset_vehicle_base)==================== - @Schema(description = "车牌号", requiredMode = Schema.RequiredMode.REQUIRED, example = "粤A12345") + // ==================== 基础信息 ==================== + @Schema(description = "车牌号", requiredMode = Schema.RequiredMode.REQUIRED, example = "沪A12345") private String plateNo; + @Schema(description = "车辆编号", example = "VEH000001") + private String vehicleNo; + @Schema(description = "车辆识别代号(VIN)", example = "LGWEF4A59NS123456") private String vin; @Schema(description = "车型ID", example = "1") private Long vehicleModelId; + @Schema(description = "运营省份", example = "广东省") + private String regionProvince; + + @Schema(description = "运营城市", example = "广州市") + private String regionCity; + @Schema(description = "发动机号", example = "ENG12345678") private String engineNo; @@ -33,76 +42,138 @@ public class VehicleRespVO { @Schema(description = "采购日期", example = "2023-06-15") private LocalDate purchaseDate; - @Schema(description = "采购价格", example = "180000.00") + @Schema(description = "采购价格", example = "150000.00") private BigDecimal purchasePrice; @Schema(description = "车身颜色", example = "白色") private String color; + @Schema(description = "出厂年份", example = "2023") + private String year; + @Schema(description = "行驶里程(公里)", example = "12580") private Integer mileage; - // ==================== 位置信息(asset_vehicle_location)==================== + @Schema(description = "行驶证检验有效期", example = "2025-07") + private String inspectExpire; + + @Schema(description = "强制报废期", example = "2038-12-31") + private LocalDate scrapDate; + + // ==================== 位置信息 ==================== @Schema(description = "停车场ID", example = "1") private Long parkingId; + @Schema(description = "停车场名称", example = "天河停车场") + private String parkingName; + @Schema(description = "停车位", example = "A1-001") private String parkingSpace; - @Schema(description = "入场时间", example = "2024-01-15 10:30:00") + @Schema(description = "GPS详细地址", example = "广东省广州市天河区天河路100号") + private String location; + + @Schema(description = "纬度", example = "23.123456") + private BigDecimal latitude; + + @Schema(description = "经度", example = "113.123456") + private BigDecimal longitude; + + @Schema(description = "GPS最后上传时间", example = "2024-02-12 14:30:00") + private LocalDateTime gpsTime; + + @Schema(description = "入场时间", example = "2024-02-01 10:00:00") private LocalDateTime entryTime; - @Schema(description = "出场时间", example = "2024-01-20 16:45:00") + @Schema(description = "出场时间", example = "2024-02-10 18:00:00") private LocalDateTime exitTime; - // ==================== 业务信息(asset_vehicle_business)==================== + // ==================== 业务信息 ==================== @Schema(description = "客户ID", example = "1") private Long customerId; + @Schema(description = "业务部门ID", example = "1") + private Long departmentId; + + @Schema(description = "业务负责人ID", example = "1") + private Long managerId; + @Schema(description = "合同ID", example = "1") private Long contractId; + @Schema(description = "登记所有权", example = "某某租赁公司") + private String ownership; + @Schema(description = "交车日期", example = "2024-01-10") private LocalDate deliveryDate; - @Schema(description = "还车日期", example = "2024-07-10") + @Schema(description = "还车日期", example = "2024-02-01") private LocalDate returnDate; - @Schema(description = "月租金", example = "3500.00") + @Schema(description = "月租金", example = "3000.00") private BigDecimal monthlyRent; - @Schema(description = "押金", example = "12000.00") + @Schema(description = "押金", example = "10000.00") private BigDecimal deposit; - // ==================== 状态信息(asset_vehicle_status)==================== - @Schema(description = "车辆状态(0=正常 1=维修中 2=报废)", example = "0") + // ==================== 状态信息 ==================== + @Schema(description = "车辆状态", example = "0") private Integer status; + @Schema(description = "运营状态", example = "2") + private Integer operateStatus; + + @Schema(description = "库位状态", example = "5") + private Integer storageStatus; + + @Schema(description = "出库状态", example = "4") + private Integer outStatus; + + @Schema(description = "预占状态", example = "0") + private Integer preemptStatus; + + @Schema(description = "整备状态", example = "3") + private Integer prepareStatus; + + @Schema(description = "过户状态", example = "0") + private Integer transferStatus; + + @Schema(description = "维修状态", example = "0") + private Integer repairStatus; + + @Schema(description = "证照状态", example = "0") + private Integer licenseStatus; + + @Schema(description = "报废状态", example = "0") + private Integer scrapStatus; + + @Schema(description = "在线状态", example = "1") + private Integer onlineStatus; + @Schema(description = "是否已备车", example = "true") private Boolean isPrepared; - @Schema(description = "是否已交车", example = "false") + @Schema(description = "是否已交车", example = "true") private Boolean isDelivered; @Schema(description = "是否已还车", example = "false") private Boolean isReturned; - @Schema(description = "上次保养日期", example = "2024-01-05") + @Schema(description = "上次保养日期", example = "2024-01-15") private LocalDate lastMaintainDate; - @Schema(description = "下次保养日期", example = "2024-04-05") + @Schema(description = "下次保养日期", example = "2024-07-15") private LocalDate nextMaintainDate; - @Schema(description = "上次年检日期", example = "2023-12-20") + @Schema(description = "上次年检日期", example = "2024-01-01") private LocalDate lastInspectDate; - @Schema(description = "下次年检日期", example = "2024-12-20") + @Schema(description = "下次年检日期", example = "2026-01-01") private LocalDate nextInspectDate; - @Schema(description = "保险到期日期", example = "2024-12-31") + @Schema(description = "保险到期日期", example = "2025-12-31") private LocalDate insuranceExpireDate; - // ==================== 系统字段 ==================== @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/customer/CustomerConvert.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/customer/CustomerConvert.java new file mode 100644 index 0000000..07cb1fc --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/customer/CustomerConvert.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.asset.convert.customer; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.asset.controller.admin.customer.vo.CustomerRespVO; +import cn.iocoder.yudao.module.asset.controller.admin.customer.vo.CustomerSaveReqVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.customer.CustomerDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 客户 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface CustomerConvert { + + CustomerConvert INSTANCE = Mappers.getMapper(CustomerConvert.class); + + CustomerDO convert(CustomerSaveReqVO bean); + + CustomerRespVO convert(CustomerDO bean); + + PageResult convertPage(PageResult page); + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/vehicle/VehicleConvert.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/vehicle/VehicleConvert.java index e34c197..e0b86b3 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/vehicle/VehicleConvert.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/vehicle/VehicleConvert.java @@ -32,21 +32,32 @@ public interface VehicleConvert { if (base != null) { vo.setId(base.getId()); vo.setPlateNo(base.getPlateNo()); + vo.setVehicleNo(base.getVehicleNo()); vo.setVin(base.getVin()); vo.setVehicleModelId(base.getVehicleModelId()); + vo.setRegionProvince(base.getRegionProvince()); + vo.setRegionCity(base.getRegionCity()); vo.setEngineNo(base.getEngineNo()); vo.setRegisterDate(base.getRegisterDate()); vo.setPurchaseDate(base.getPurchaseDate()); vo.setPurchasePrice(base.getPurchasePrice()); vo.setColor(base.getColor()); + vo.setYear(base.getYear()); vo.setMileage(base.getMileage()); + vo.setInspectExpire(base.getInspectExpire()); + vo.setScrapDate(base.getScrapDate()); vo.setCreateTime(base.getCreateTime()); } // 位置信息 if (location != null) { vo.setParkingId(location.getParkingId()); + vo.setParkingName(location.getParkingName()); vo.setParkingSpace(location.getParkingSpace()); + vo.setLocation(location.getLocation()); + vo.setLatitude(location.getLatitude()); + vo.setLongitude(location.getLongitude()); + vo.setGpsTime(location.getGpsTime()); vo.setEntryTime(location.getEntryTime()); vo.setExitTime(location.getExitTime()); } @@ -54,7 +65,10 @@ public interface VehicleConvert { // 业务信息 if (business != null) { vo.setCustomerId(business.getCustomerId()); + vo.setDepartmentId(business.getDepartmentId()); + vo.setManagerId(business.getManagerId()); vo.setContractId(business.getContractId()); + vo.setOwnership(business.getOwnership()); vo.setDeliveryDate(business.getDeliveryDate()); vo.setReturnDate(business.getReturnDate()); vo.setMonthlyRent(business.getMonthlyRent()); @@ -64,6 +78,16 @@ public interface VehicleConvert { // 状态信息 if (status != null) { vo.setStatus(status.getStatus()); + vo.setOperateStatus(status.getOperateStatus()); + vo.setStorageStatus(status.getStorageStatus()); + vo.setOutStatus(status.getOutStatus()); + vo.setPreemptStatus(status.getPreemptStatus()); + vo.setPrepareStatus(status.getPrepareStatus()); + vo.setTransferStatus(status.getTransferStatus()); + vo.setRepairStatus(status.getRepairStatus()); + vo.setLicenseStatus(status.getLicenseStatus()); + vo.setScrapStatus(status.getScrapStatus()); + vo.setOnlineStatus(status.getOnlineStatus()); vo.setIsPrepared(status.getIsPrepared()); vo.setIsDelivered(status.getIsDelivered()); vo.setIsReturned(status.getIsReturned()); diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/customer/CustomerDO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/customer/CustomerDO.java new file mode 100644 index 0000000..aeb4d3e --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/customer/CustomerDO.java @@ -0,0 +1,132 @@ +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.*; + +import java.math.BigDecimal; + +/** + * 客户信息 DO + * + * @author 芋道源码 + */ +@TableName("asset_customer") +@KeySequence("asset_customer_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CustomerDO extends BaseDO { + + /** + * 主键ID + */ + @TableId + private Long id; + + /** + * 客户编号 + */ + private String customerNo; + + /** + * 客户名称 + */ + private String customerName; + + /** + * 客户类型(0=个人 1=企业) + */ + private Integer customerType; + + /** + * 联系人 + */ + private String contactPerson; + + /** + * 联系电话 + */ + private String contactPhone; + + /** + * 联系邮箱 + */ + private String contactEmail; + + /** + * 联系地址 + */ + 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 remark; + + /** + * 状态(0=正常 1=冻结 2=黑名单) + */ + private Integer status; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/vehicle/VehicleBaseDO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/vehicle/VehicleBaseDO.java index 3ca925c..25a5167 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/vehicle/VehicleBaseDO.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/vehicle/VehicleBaseDO.java @@ -39,11 +39,26 @@ public class VehicleBaseDO extends BaseDO { */ private String plateNo; + /** + * 车辆编号 + */ + private String vehicleNo; + /** * 车型ID */ private Long vehicleModelId; + /** + * 运营省份 + */ + private String regionProvince; + + /** + * 运营城市 + */ + private String regionCity; + /** * 发动机号 */ @@ -69,9 +84,24 @@ public class VehicleBaseDO extends BaseDO { */ private String color; + /** + * 出厂年份 + */ + private String year; + /** * 行驶里程(公里) */ private Integer mileage; + /** + * 行驶证检验有效期(格式:YYYY-MM) + */ + private String inspectExpire; + + /** + * 强制报废期 + */ + private LocalDate scrapDate; + } diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/vehicle/VehicleBusinessDO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/vehicle/VehicleBusinessDO.java index 07a5d0c..1aa21af 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/vehicle/VehicleBusinessDO.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/vehicle/VehicleBusinessDO.java @@ -40,11 +40,26 @@ public class VehicleBusinessDO extends BaseDO { */ private Long customerId; + /** + * 业务部门ID + */ + private Long departmentId; + + /** + * 业务负责人ID + */ + private Long managerId; + /** * 合同ID */ private Long contractId; + /** + * 登记所有权 + */ + private String ownership; + /** * 交车日期 */ diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/vehicle/VehicleLocationDO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/vehicle/VehicleLocationDO.java index 0862125..a4eb5de 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/vehicle/VehicleLocationDO.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/vehicle/VehicleLocationDO.java @@ -39,11 +39,36 @@ public class VehicleLocationDO extends BaseDO { */ private Long parkingId; + /** + * 停车场名称(冗余字段) + */ + private String parkingName; + /** * 停车位 */ private String parkingSpace; + /** + * GPS详细地址 + */ + private String location; + + /** + * 纬度 + */ + private java.math.BigDecimal latitude; + + /** + * 经度 + */ + private java.math.BigDecimal longitude; + + /** + * GPS最后上传时间 + */ + private LocalDateTime gpsTime; + /** * 入场时间 */ diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/vehicle/VehicleStatusDO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/vehicle/VehicleStatusDO.java index ac2671e..14902b8 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/vehicle/VehicleStatusDO.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/vehicle/VehicleStatusDO.java @@ -39,6 +39,56 @@ public class VehicleStatusDO extends BaseDO { */ private Integer status; + /** + * 运营状态(0=待运营 1=库存 2=租赁 3=自营 4=退出运营) + */ + private Integer operateStatus; + + /** + * 库位状态(0=新车入库-待验车 1=新车入库-证照办理 2=库存车-可交付车 3=库存车-不可交付车 4=库存车-呆滞车 5=已交付车-租赁交车 6=已交付车-自营交车 7=已交付车-替换交车 8=退出运营-报废车 9=退出运营-三方退租车 10=退出运营-过户售车) + */ + private Integer storageStatus; + + /** + * 出库状态(0=无 1=异动出库 2=调拨出库 3=展示出库 4=租赁交车 5=自营交车 6=替换交车 7=过户售车 8=外租退车 9=报废出库) + */ + private Integer outStatus; + + /** + * 预占状态(0=未预占 1=已预占) + */ + private Integer preemptStatus; + + /** + * 整备状态(0=无 1=待整备 2=整备中 3=正常) + */ + private Integer prepareStatus; + + /** + * 过户状态(0=无 1=过户中 2=内部过户完成 3=销售过户完成) + */ + private Integer transferStatus; + + /** + * 维修状态(0=正常 1=待服务站接单 2=维修中) + */ + private Integer repairStatus; + + /** + * 证照状态(0=正常 1=异常) + */ + private Integer licenseStatus; + + /** + * 报废状态(0=无 1=报废中 2=已报废) + */ + private Integer scrapStatus; + + /** + * 在线状态(0=离线 1=在线) + */ + private Integer onlineStatus; + /** * 是否已备车 */ diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/customer/CustomerMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/customer/CustomerMapper.java new file mode 100644 index 0000000..e51c597 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/customer/CustomerMapper.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.asset.dal.mysql.customer; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.asset.controller.admin.customer.vo.CustomerPageReqVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.customer.CustomerDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 客户信息 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface CustomerMapper extends BaseMapperX { + + default PageResult selectPage(CustomerPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(CustomerDO::getCustomerName, reqVO.getCustomerName()) + .likeIfPresent(CustomerDO::getContactPhone, reqVO.getContactPhone()) + .eqIfPresent(CustomerDO::getCustomerType, reqVO.getCustomerType()) + .eqIfPresent(CustomerDO::getStatus, reqVO.getStatus()) + .orderByDesc(CustomerDO::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 69ac3f2..d3049b8 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 @@ -17,4 +17,7 @@ public interface ErrorCodeConstants { // ========== 车型参数管理 1-008-002-000 ========== ErrorCode VEHICLE_MODEL_NOT_EXISTS = new ErrorCode(1_008_002_000, "车型参数不存在"); + // ========== 客户管理 1-008-003-000 ========== + ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_008_003_000, "客户不存在"); + } diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/customer/CustomerService.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/customer/CustomerService.java new file mode 100644 index 0000000..b11f2a8 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/customer/CustomerService.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.asset.service.customer; + +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.dal.dataobject.customer.CustomerDO; + +import jakarta.validation.Valid; + +/** + * 客户信息 Service 接口 + * + * @author 芋道源码 + */ +public interface CustomerService { + + /** + * 创建客户 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createCustomer(@Valid CustomerSaveReqVO createReqVO); + + /** + * 更新客户 + * + * @param updateReqVO 更新信息 + */ + void updateCustomer(@Valid CustomerSaveReqVO updateReqVO); + + /** + * 删除客户 + * + * @param id 编号 + */ + void deleteCustomer(Long id); + + /** + * 获得客户 + * + * @param id 编号 + * @return 客户 + */ + CustomerDO getCustomer(Long id); + + /** + * 获得客户分页 + * + * @param pageReqVO 分页查询 + * @return 客户分页 + */ + PageResult getCustomerPage(CustomerPageReqVO pageReqVO); + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/customer/CustomerServiceImpl.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/customer/CustomerServiceImpl.java new file mode 100644 index 0000000..1d3f5de --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/customer/CustomerServiceImpl.java @@ -0,0 +1,89 @@ +package cn.iocoder.yudao.module.asset.service.customer; + +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.CustomerDO; +import cn.iocoder.yudao.module.asset.dal.mysql.customer.CustomerMapper; +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.CUSTOMER_NOT_EXISTS; + +/** + * 客户信息 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +@Slf4j +public class CustomerServiceImpl implements CustomerService { + + @Resource + private CustomerMapper customerMapper; + + @Override + public Long createCustomer(CustomerSaveReqVO createReqVO) { + // 转换并插入 + CustomerDO customer = CustomerConvert.INSTANCE.convert(createReqVO); + + // 生成客户编号 + if (customer.getCustomerNo() == null) { + customer.setCustomerNo(generateCustomerNo()); + } + + customerMapper.insert(customer); + return customer.getId(); + } + + @Override + public void updateCustomer(CustomerSaveReqVO updateReqVO) { + // 校验存在 + validateCustomerExists(updateReqVO.getId()); + + // 转换并更新 + CustomerDO updateObj = CustomerConvert.INSTANCE.convert(updateReqVO); + 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 CustomerDO getCustomer(Long id) { + return customerMapper.selectById(id); + } + + @Override + public PageResult getCustomerPage(CustomerPageReqVO pageReqVO) { + return customerMapper.selectPage(pageReqVO); + } + + /** + * 生成客户编号 + */ + private String generateCustomerNo() { + // 查询最大ID + Long maxId = customerMapper.selectCount(); + return String.format("CUST%06d", maxId + 1); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/test/java/cn/iocoder/yudao/module/asset/service/customer/CustomerServiceImplTest.java b/yudao-module-asset/yudao-module-asset-server/src/test/java/cn/iocoder/yudao/module/asset/service/customer/CustomerServiceImplTest.java new file mode 100644 index 0000000..a8f1020 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/test/java/cn/iocoder/yudao/module/asset/service/customer/CustomerServiceImplTest.java @@ -0,0 +1,228 @@ +package cn.iocoder.yudao.module.asset.service.customer; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +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.dal.dataobject.customer.CustomerDO; +import cn.iocoder.yudao.module.asset.dal.mysql.customer.CustomerMapper; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import jakarta.annotation.Resource; +import java.math.BigDecimal; + +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.module.asset.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; + +/** + * 客户管理 Service 测试类 + * + * @author 芋道源码 + */ +@Import(CustomerServiceImpl.class) +public class CustomerServiceImplTest extends BaseDbUnitTest { + + @Resource + private CustomerServiceImpl customerService; + + @Resource + private CustomerMapper customerMapper; + + @Test + public void testCreateCustomer_success() { + // 准备参数 + CustomerSaveReqVO createReqVO = randomPojo(CustomerSaveReqVO.class, o -> { + o.setCustomerName("测试客户"); + o.setCustomerType(0); + o.setContactPhone("13800138000"); + o.setContactEmail("test@example.com"); + o.setIdCardNo("310101199001011234"); + o.setCreditLevel(1); + o.setDepositAmount(new BigDecimal("5000.00")); + o.setStatus(0); + }); + + // 调用 + Long customerId = customerService.createCustomer(createReqVO); + + // 断言 + assertNotNull(customerId); + CustomerDO customer = customerMapper.selectById(customerId); + assertNotNull(customer); + assertEquals("测试客户", customer.getCustomerName()); + assertEquals(0, customer.getCustomerType()); + assertEquals("13800138000", customer.getContactPhone()); + assertNotNull(customer.getCustomerNo()); + assertTrue(customer.getCustomerNo().startsWith("CUST")); + } + + @Test + public void testUpdateCustomer_success() { + // mock 数据 + CustomerDO dbCustomer = new CustomerDO(); + dbCustomer.setCustomerNo("CUST000001"); + dbCustomer.setCustomerName("原客户名"); + dbCustomer.setCustomerType(0); + dbCustomer.setContactPhone("13800138000"); + dbCustomer.setCreditLevel(1); + dbCustomer.setDepositAmount(new BigDecimal("5000.00")); + dbCustomer.setStatus(0); + customerMapper.insert(dbCustomer); + + // 准备参数 + CustomerSaveReqVO updateReqVO = new CustomerSaveReqVO(); + updateReqVO.setId(dbCustomer.getId()); + updateReqVO.setCustomerName("新客户名"); + updateReqVO.setCustomerType(0); + updateReqVO.setContactPhone("13900139000"); + updateReqVO.setCreditLevel(2); + updateReqVO.setDepositAmount(new BigDecimal("8000.00")); + updateReqVO.setStatus(0); + + // 调用 + customerService.updateCustomer(updateReqVO); + + // 断言 + CustomerDO customer = customerMapper.selectById(updateReqVO.getId()); + assertEquals("新客户名", customer.getCustomerName()); + assertEquals("13900139000", customer.getContactPhone()); + assertEquals(2, customer.getCreditLevel()); + } + + @Test + public void testUpdateCustomer_notExists() { + // 准备参数 + CustomerSaveReqVO updateReqVO = randomPojo(CustomerSaveReqVO.class, o -> { + o.setId(999999L); + o.setCustomerName("不存在的客户"); + o.setCustomerType(0); + o.setStatus(0); + }); + + // 调用并断言异常 + assertServiceException(() -> customerService.updateCustomer(updateReqVO), CUSTOMER_NOT_EXISTS); + } + + @Test + public void testDeleteCustomer_success() { + // mock 数据 + CustomerDO dbCustomer = new CustomerDO(); + dbCustomer.setCustomerNo("CUST000001"); + dbCustomer.setCustomerName("测试客户"); + dbCustomer.setCustomerType(0); + dbCustomer.setCreditLevel(1); + dbCustomer.setDepositAmount(new BigDecimal("5000.00")); + dbCustomer.setStatus(0); + customerMapper.insert(dbCustomer); + + // 调用 + customerService.deleteCustomer(dbCustomer.getId()); + + // 断言 + assertNull(customerMapper.selectById(dbCustomer.getId())); + } + + @Test + public void testDeleteCustomer_notExists() { + // 调用并断言异常 + assertServiceException(() -> customerService.deleteCustomer(999999L), CUSTOMER_NOT_EXISTS); + } + + @Test + public void testGetCustomer() { + // mock 数据 + CustomerDO dbCustomer = new CustomerDO(); + dbCustomer.setCustomerNo("CUST000001"); + dbCustomer.setCustomerName("测试客户"); + dbCustomer.setCustomerType(0); + dbCustomer.setCreditLevel(1); + dbCustomer.setDepositAmount(new BigDecimal("5000.00")); + dbCustomer.setStatus(0); + customerMapper.insert(dbCustomer); + + // 调用 + CustomerDO customer = customerService.getCustomer(dbCustomer.getId()); + + // 断言 + assertNotNull(customer); + assertEquals("测试客户", customer.getCustomerName()); + } + + @Test + public void testGetCustomerPage() { + // mock 数据 + CustomerDO dbCustomer1 = new CustomerDO(); + dbCustomer1.setCustomerNo("CUST000001"); + dbCustomer1.setCustomerName("张三"); + dbCustomer1.setCustomerType(0); + dbCustomer1.setContactPhone("13800138001"); + dbCustomer1.setCreditLevel(1); + dbCustomer1.setDepositAmount(new BigDecimal("5000.00")); + dbCustomer1.setStatus(0); + customerMapper.insert(dbCustomer1); + + CustomerDO dbCustomer2 = new CustomerDO(); + dbCustomer2.setCustomerNo("CUST000002"); + dbCustomer2.setCustomerName("李四"); + dbCustomer2.setCustomerType(1); + dbCustomer2.setContactPhone("13800138002"); + dbCustomer2.setCreditLevel(1); + dbCustomer2.setDepositAmount(new BigDecimal("5000.00")); + dbCustomer2.setStatus(0); + customerMapper.insert(dbCustomer2); + + CustomerDO dbCustomer3 = new CustomerDO(); + dbCustomer3.setCustomerNo("CUST000003"); + dbCustomer3.setCustomerName("王五"); + dbCustomer3.setCustomerType(0); + dbCustomer3.setContactPhone("13800138003"); + dbCustomer3.setCreditLevel(1); + dbCustomer3.setDepositAmount(new BigDecimal("5000.00")); + dbCustomer3.setStatus(1); + customerMapper.insert(dbCustomer3); + + // 测试 customerName 模糊查询 + CustomerPageReqVO reqVO = new CustomerPageReqVO(); + reqVO.setCustomerName("张"); + reqVO.setPageNo(1); + reqVO.setPageSize(10); + + PageResult pageResult = customerService.getCustomerPage(reqVO); + assertEquals(1, pageResult.getTotal()); + assertEquals("张三", pageResult.getList().get(0).getCustomerName()); + + // 测试 customerType 筛选 + reqVO = new CustomerPageReqVO(); + reqVO.setCustomerType(1); + reqVO.setPageNo(1); + reqVO.setPageSize(10); + + pageResult = customerService.getCustomerPage(reqVO); + assertEquals(1, pageResult.getTotal()); + assertEquals("李四", pageResult.getList().get(0).getCustomerName()); + + // 测试 status 筛选 + reqVO = new CustomerPageReqVO(); + reqVO.setStatus(1); + reqVO.setPageNo(1); + reqVO.setPageSize(10); + + pageResult = customerService.getCustomerPage(reqVO); + assertEquals(1, pageResult.getTotal()); + assertEquals("王五", pageResult.getList().get(0).getCustomerName()); + + // 测试 contactPhone 模糊查询 + reqVO = new CustomerPageReqVO(); + reqVO.setContactPhone("138001"); + reqVO.setPageNo(1); + reqVO.setPageSize(10); + + pageResult = customerService.getCustomerPage(reqVO); + assertEquals(3, pageResult.getTotal()); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/test/resources/application-unit-test.yaml b/yudao-module-asset/yudao-module-asset-server/src/test/resources/application-unit-test.yaml new file mode 100644 index 0000000..4c85137 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/test/resources/application-unit-test.yaml @@ -0,0 +1,25 @@ +spring: + application: + name: asset-server-test + sql: + init: + mode: always + schema-locations: classpath:sql/create_tables.sql + cloud: + nacos: + discovery: + enabled: false + config: + enabled: false + +yudao: + info: + version: 1.0.0-test + base-package: cn.iocoder.yudao.module.asset + web: + admin-api: + prefix: /admin-api + controller: '**.controller.admin.**' + security: + permit-all-urls: + - /admin-api/asset/** diff --git a/yudao-module-asset/yudao-module-asset-server/src/test/resources/sql/clean.sql b/yudao-module-asset/yudao-module-asset-server/src/test/resources/sql/clean.sql new file mode 100644 index 0000000..4d8eca2 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/test/resources/sql/clean.sql @@ -0,0 +1,2 @@ +-- 清理测试数据 +DELETE FROM asset_customer; diff --git a/yudao-module-asset/yudao-module-asset-server/src/test/resources/sql/create_tables.sql b/yudao-module-asset/yudao-module-asset-server/src/test/resources/sql/create_tables.sql new file mode 100644 index 0000000..1e5f3e7 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/test/resources/sql/create_tables.sql @@ -0,0 +1,30 @@ +-- 客户信息表 +CREATE TABLE IF NOT EXISTS asset_customer ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + customer_no VARCHAR(50) NOT NULL, + customer_name VARCHAR(100) NOT NULL, + customer_type TINYINT NOT NULL DEFAULT 0, + contact_person VARCHAR(50), + contact_phone VARCHAR(20), + contact_email VARCHAR(100), + contact_address VARCHAR(255), + id_card_no VARCHAR(18), + id_card_front_url VARCHAR(255), + id_card_back_url VARCHAR(255), + driver_license_no VARCHAR(50), + driver_license_url VARCHAR(255), + company_name VARCHAR(200), + unified_social_credit_code VARCHAR(50), + business_license_url VARCHAR(255), + legal_person VARCHAR(50), + credit_level TINYINT DEFAULT 0, + deposit_amount DECIMAL(10,2) DEFAULT 0.00, + remark VARCHAR(500), + status TINYINT NOT NULL DEFAULT 0, + creator VARCHAR(64) DEFAULT '', + create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater VARCHAR(64) DEFAULT '', + update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted TINYINT NOT NULL DEFAULT 0, + tenant_id BIGINT NOT NULL DEFAULT 0 +);