diff --git a/yudao-module-asset/sql/mysql/2026-03-13-inspection-tables.sql b/yudao-module-asset/sql/mysql/2026-03-13-inspection-tables.sql new file mode 100644 index 0000000..c0fd0f6 --- /dev/null +++ b/yudao-module-asset/sql/mysql/2026-03-13-inspection-tables.sql @@ -0,0 +1,88 @@ +-- ============================================= +-- 验车模板与验车记录表 +-- 创建时间: 2026-03-13 +-- ============================================= + +-- 验车模板 +CREATE TABLE IF NOT EXISTS `asset_inspection_template` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `code` varchar(50) NOT NULL COMMENT '模板编码', + `name` varchar(100) NOT NULL COMMENT '模板名称', + `biz_type` tinyint NOT NULL COMMENT '业务类型(1=备车 2=交车 3=还车)', + `vehicle_type` varchar(50) DEFAULT NULL COMMENT '车辆类型', + `status` tinyint DEFAULT 1 COMMENT '状态(0=禁用 1=启用)', + `remark` varchar(500) DEFAULT NULL 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`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='验车模板'; + +-- 验车模板检查项 +CREATE TABLE IF NOT EXISTS `asset_inspection_template_item` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `template_id` bigint NOT NULL COMMENT '模板ID', + `category` varchar(50) NOT NULL COMMENT '分类', + `item_name` varchar(100) NOT NULL COMMENT '检查项名称', + `item_code` varchar(50) NOT NULL COMMENT '检查项编码', + `input_type` varchar(20) DEFAULT 'checkbox' COMMENT '输入类型', + `sort` int DEFAULT 0 COMMENT '排序', + `required` tinyint DEFAULT 1 COMMENT '是否必填(0=否 1=是)', + `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`), + INDEX `idx_template_id` (`template_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='验车模板检查项'; + +-- 验车记录 +CREATE TABLE IF NOT EXISTS `asset_inspection_record` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `record_code` varchar(50) NOT NULL COMMENT '记录编码', + `template_id` bigint NOT NULL COMMENT '模板ID', + `source_type` tinyint NOT NULL COMMENT '来源类型(1=备车 2=交车 3=还车)', + `source_id` bigint NOT NULL COMMENT '来源ID', + `vehicle_id` bigint NOT NULL COMMENT '车辆ID', + `inspector_name` varchar(50) DEFAULT NULL COMMENT '检查人', + `inspection_time` datetime DEFAULT NULL COMMENT '检查时间', + `status` tinyint DEFAULT 0 COMMENT '状态(0=待检 1=检查中 2=已完成)', + `overall_result` tinyint DEFAULT NULL COMMENT '总体结果(1=通过 2=不通过 3=不适用)', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `cloned_from_id` bigint DEFAULT NULL COMMENT '克隆来源记录ID', + `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`), + INDEX `idx_vehicle_source` (`vehicle_id`, `source_type`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='验车记录'; + +-- 验车记录检查项 +CREATE TABLE IF NOT EXISTS `asset_inspection_record_item` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `record_id` bigint NOT NULL COMMENT '记录ID', + `item_code` varchar(50) NOT NULL COMMENT '检查项编码', + `category` varchar(50) NOT NULL COMMENT '分类', + `item_name` varchar(100) NOT NULL COMMENT '检查项名称', + `input_type` varchar(20) DEFAULT 'checkbox' COMMENT '输入类型', + `result` tinyint DEFAULT NULL COMMENT '检查结果(1=通过 2=不通过 3=不适用)', + `value` varchar(200) DEFAULT NULL COMMENT '检查值', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `image_urls` varchar(2000) DEFAULT NULL COMMENT '图片URL列表', + `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`), + INDEX `idx_record_id` (`record_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='验车记录检查项'; diff --git a/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/inspection/InspectionResultEnum.java b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/inspection/InspectionResultEnum.java new file mode 100644 index 0000000..331f811 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/inspection/InspectionResultEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.asset.enums.inspection; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 验车结果枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum InspectionResultEnum { + + PASS(1, "通过"), + FAIL(2, "不通过"), + NA(3, "不适用"); + + /** + * 结果 + */ + private final Integer result; + /** + * 名称 + */ + private final String name; + + public static InspectionResultEnum valueOf(Integer result) { + return Arrays.stream(values()) + .filter(item -> item.getResult().equals(result)) + .findFirst() + .orElse(null); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/inspection/InspectionSourceTypeEnum.java b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/inspection/InspectionSourceTypeEnum.java new file mode 100644 index 0000000..886e5dc --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/inspection/InspectionSourceTypeEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.asset.enums.inspection; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 验车来源类型枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum InspectionSourceTypeEnum { + + PREPARE(1, "备车"), + DELIVERY(2, "交车"), + RETURN(3, "还车"); + + /** + * 类型 + */ + private final Integer type; + /** + * 名称 + */ + private final String name; + + public static InspectionSourceTypeEnum valueOf(Integer type) { + return Arrays.stream(values()) + .filter(item -> item.getType().equals(type)) + .findFirst() + .orElse(null); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/inspection/InspectionStatusEnum.java b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/inspection/InspectionStatusEnum.java new file mode 100644 index 0000000..735785e --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/inspection/InspectionStatusEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.asset.enums.inspection; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 验车状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum InspectionStatusEnum { + + PENDING(0, "待检"), + IN_PROGRESS(1, "检查中"), + COMPLETED(2, "已完成"); + + /** + * 状态 + */ + private final Integer status; + /** + * 名称 + */ + private final String name; + + public static InspectionStatusEnum valueOf(Integer status) { + return Arrays.stream(values()) + .filter(item -> item.getStatus().equals(status)) + .findFirst() + .orElse(null); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/InspectionRecordController.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/InspectionRecordController.java new file mode 100644 index 0000000..96ca11d --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/InspectionRecordController.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.asset.controller.admin.inspection; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.asset.controller.admin.inspection.vo.InspectionRecordDetailVO; +import cn.iocoder.yudao.module.asset.controller.admin.inspection.vo.InspectionRecordItemUpdateReqVO; +import cn.iocoder.yudao.module.asset.service.inspection.InspectionRecordService; +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/inspection-record") +@Validated +public class InspectionRecordController { + + @Resource + private InspectionRecordService inspectionRecordService; + + @GetMapping("/get") + @Operation(summary = "获得验车记录详情") + @Parameter(name = "id", description = "编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('asset:inspection-record:query')") + public CommonResult getRecordDetail(@RequestParam("id") Long id) { + return success(inspectionRecordService.getRecordDetail(id)); + } + + @PutMapping("/update-item") + @Operation(summary = "更新验车记录检查项") + @PreAuthorize("@ss.hasPermission('asset:inspection-record:update')") + public CommonResult updateRecordItem(@Valid @RequestBody InspectionRecordItemUpdateReqVO updateReqVO) { + inspectionRecordService.updateRecordItem(updateReqVO); + return success(true); + } + + @PostMapping("/complete") + @Operation(summary = "完成验车记录") + @Parameter(name = "id", description = "记录ID", required = true, example = "1") + @Parameter(name = "inspectorName", description = "检查人", required = true, example = "张三") + @PreAuthorize("@ss.hasPermission('asset:inspection-record:update')") + public CommonResult completeRecord(@RequestParam("id") Long id, + @RequestParam("inspectorName") String inspectorName) { + inspectionRecordService.completeRecord(id, inspectorName); + return success(true); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/InspectionTemplateController.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/InspectionTemplateController.java new file mode 100644 index 0000000..6b40105 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/InspectionTemplateController.java @@ -0,0 +1,75 @@ +package cn.iocoder.yudao.module.asset.controller.admin.inspection; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.asset.controller.admin.inspection.vo.*; +import cn.iocoder.yudao.module.asset.convert.inspection.InspectionConvert; +import cn.iocoder.yudao.module.asset.dal.dataobject.inspection.InspectionTemplateDO; +import cn.iocoder.yudao.module.asset.service.inspection.InspectionTemplateService; +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/inspection-template") +@Validated +public class InspectionTemplateController { + + @Resource + private InspectionTemplateService inspectionTemplateService; + + @PostMapping("/create") + @Operation(summary = "创建验车模板") + @PreAuthorize("@ss.hasPermission('asset:inspection-template:create')") + public CommonResult createTemplate(@Valid @RequestBody InspectionTemplateSaveReqVO createReqVO) { + return success(inspectionTemplateService.createTemplate(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新验车模板") + @PreAuthorize("@ss.hasPermission('asset:inspection-template:update')") + public CommonResult updateTemplate(@Valid @RequestBody InspectionTemplateSaveReqVO updateReqVO) { + inspectionTemplateService.updateTemplate(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除验车模板") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('asset:inspection-template:delete')") + public CommonResult deleteTemplate(@RequestParam("id") Long id) { + inspectionTemplateService.deleteTemplate(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得验车模板详情") + @Parameter(name = "id", description = "编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('asset:inspection-template:query')") + public CommonResult getTemplate(@RequestParam("id") Long id) { + return success(inspectionTemplateService.getTemplate(id)); + } + + @GetMapping("/page") + @Operation(summary = "获得验车模板分页") + @PreAuthorize("@ss.hasPermission('asset:inspection-template:query')") + public CommonResult> getTemplatePage(@Valid InspectionTemplatePageReqVO pageReqVO) { + PageResult pageResult = inspectionTemplateService.getTemplatePage(pageReqVO); + return success(InspectionConvert.INSTANCE.convertPage(pageResult)); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/vo/InspectionRecordDetailVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/vo/InspectionRecordDetailVO.java new file mode 100644 index 0000000..d15abce --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/vo/InspectionRecordDetailVO.java @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.asset.controller.admin.inspection.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 验车记录详情 Response VO + */ +@Schema(description = "管理后台 - 验车记录详情 Response VO") +@Data +public class InspectionRecordDetailVO { + + @Schema(description = "主键ID", example = "1") + private Long id; + + @Schema(description = "记录编码", example = "BC-20260313-001") + private String recordCode; + + @Schema(description = "模板ID", example = "1") + private Long templateId; + + @Schema(description = "来源类型(1=备车 2=交车 3=还车)", example = "1") + private Integer sourceType; + + @Schema(description = "来源ID", example = "1") + private Long sourceId; + + @Schema(description = "车辆ID", example = "1") + private Long vehicleId; + + @Schema(description = "检查人", example = "张三") + private String inspectorName; + + @Schema(description = "检查时间") + private LocalDateTime inspectionTime; + + @Schema(description = "状态(0=待检 1=检查中 2=已完成)", example = "0") + private Integer status; + + @Schema(description = "总体结果(1=通过 2=不通过 3=不适用)", example = "1") + private Integer overallResult; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "克隆来源记录ID", example = "1") + private Long clonedFromId; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "检查项列表") + private List items; + + /** + * 验车记录检查项 VO + */ + @Schema(description = "验车记录检查项 VO") + @Data + public static class InspectionRecordItemVO { + + @Schema(description = "主键ID", example = "1") + private Long id; + + @Schema(description = "检查项编码", example = "BODY_PAINT") + private String itemCode; + + @Schema(description = "分类", example = "外观检查") + private String category; + + @Schema(description = "检查项名称", example = "车身漆面") + private String itemName; + + @Schema(description = "输入类型", example = "checkbox") + private String inputType; + + @Schema(description = "检查结果(1=通过 2=不通过 3=不适用)", example = "1") + private Integer result; + + @Schema(description = "检查值", example = "正常") + private String value; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "图片URL列表") + private String imageUrls; + + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/vo/InspectionRecordItemUpdateReqVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/vo/InspectionRecordItemUpdateReqVO.java new file mode 100644 index 0000000..8fac63f --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/vo/InspectionRecordItemUpdateReqVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.asset.controller.admin.inspection.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotNull; + +/** + * 验车记录检查项更新 Request VO + */ +@Schema(description = "管理后台 - 验车记录检查项更新 Request VO") +@Data +public class InspectionRecordItemUpdateReqVO { + + @Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "主键ID不能为空") + private Long id; + + @Schema(description = "检查结果(1=通过 2=不通过 3=不适用)", example = "1") + private Integer result; + + @Schema(description = "检查值", example = "正常") + private String value; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "图片URL列表") + private String imageUrls; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/vo/InspectionTemplateItemVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/vo/InspectionTemplateItemVO.java new file mode 100644 index 0000000..3dc0db0 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/vo/InspectionTemplateItemVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.asset.controller.admin.inspection.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotBlank; + +/** + * 验车模板检查项 VO + */ +@Schema(description = "管理后台 - 验车模板检查项 VO") +@Data +public class InspectionTemplateItemVO { + + @Schema(description = "主键ID", example = "1") + private Long id; + + @Schema(description = "分类", requiredMode = Schema.RequiredMode.REQUIRED, example = "外观检查") + @NotBlank(message = "分类不能为空") + private String category; + + @Schema(description = "检查项名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "车身漆面") + @NotBlank(message = "检查项名称不能为空") + private String itemName; + + @Schema(description = "检查项编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "BODY_PAINT") + @NotBlank(message = "检查项编码不能为空") + private String itemCode; + + @Schema(description = "输入类型", example = "checkbox") + private String inputType; + + @Schema(description = "排序", example = "0") + private Integer sort; + + @Schema(description = "是否必填(0=否 1=是)", example = "1") + private Integer required; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/vo/InspectionTemplatePageReqVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/vo/InspectionTemplatePageReqVO.java new file mode 100644 index 0000000..0d3cf2d --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/vo/InspectionTemplatePageReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.asset.controller.admin.inspection.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; + +/** + * 验车模板分页查询 Request VO + */ +@Schema(description = "管理后台 - 验车模板分页查询 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class InspectionTemplatePageReqVO extends PageParam { + + @Schema(description = "模板编码", example = "TPL-BC-001") + private String code; + + @Schema(description = "模板名称", example = "备车检查模板") + private String name; + + @Schema(description = "业务类型(1=备车 2=交车 3=还车)", example = "1") + private Integer bizType; + + @Schema(description = "车辆类型", example = "重卡") + private String vehicleType; + + @Schema(description = "状态(0=禁用 1=启用)", example = "1") + private Integer status; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/vo/InspectionTemplateRespVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/vo/InspectionTemplateRespVO.java new file mode 100644 index 0000000..811516c --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/vo/InspectionTemplateRespVO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.asset.controller.admin.inspection.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 验车模板 Response VO + */ +@Schema(description = "管理后台 - 验车模板 Response VO") +@Data +public class InspectionTemplateRespVO { + + @Schema(description = "主键ID", example = "1") + private Long id; + + @Schema(description = "模板编码", example = "TPL-BC-001") + private String code; + + @Schema(description = "模板名称", example = "备车检查模板") + private String name; + + @Schema(description = "业务类型(1=备车 2=交车 3=还车)", example = "1") + private Integer bizType; + + @Schema(description = "车辆类型", example = "重卡") + private String vehicleType; + + @Schema(description = "状态(0=禁用 1=启用)", example = "1") + private Integer status; + + @Schema(description = "备注", example = "备车检查模板") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "检查项列表") + private List items; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/vo/InspectionTemplateSaveReqVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/vo/InspectionTemplateSaveReqVO.java new file mode 100644 index 0000000..fa91239 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/inspection/vo/InspectionTemplateSaveReqVO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.asset.controller.admin.inspection.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import java.util.List; + +/** + * 验车模板创建/更新 Request VO + */ +@Schema(description = "管理后台 - 验车模板创建/更新 Request VO") +@Data +public class InspectionTemplateSaveReqVO { + + @Schema(description = "主键ID", example = "1") + private Long id; + + @Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "TPL-BC-001") + @NotBlank(message = "模板编码不能为空") + private String code; + + @Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "备车检查模板") + @NotBlank(message = "模板名称不能为空") + private String name; + + @Schema(description = "业务类型(1=备车 2=交车 3=还车)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "业务类型不能为空") + private Integer bizType; + + @Schema(description = "车辆类型", example = "重卡") + private String vehicleType; + + @Schema(description = "状态(0=禁用 1=启用)", example = "1") + private Integer status; + + @Schema(description = "备注", example = "备车检查模板") + private String remark; + + @Schema(description = "检查项列表") + @Valid + private List items; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/inspection/InspectionConvert.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/inspection/InspectionConvert.java new file mode 100644 index 0000000..13f143f --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/inspection/InspectionConvert.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.asset.convert.inspection; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.asset.controller.admin.inspection.vo.*; +import cn.iocoder.yudao.module.asset.dal.dataobject.inspection.*; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 验车模板/记录 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface InspectionConvert { + + InspectionConvert INSTANCE = Mappers.getMapper(InspectionConvert.class); + + InspectionTemplateDO convert(InspectionTemplateSaveReqVO bean); + + InspectionTemplateRespVO convert(InspectionTemplateDO bean); + + PageResult convertPage(PageResult page); + + List convertItemList(List list); + + InspectionTemplateItemDO convertItem(InspectionTemplateItemVO bean); + + List convertItemVOList(List list); + + InspectionTemplateItemVO convertItemVO(InspectionTemplateItemDO bean); + + InspectionRecordDetailVO convertRecordDetail(InspectionRecordDO bean); + + List convertRecordItemVOList(List list); + + InspectionRecordDetailVO.InspectionRecordItemVO convertRecordItemVO(InspectionRecordItemDO bean); + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/inspection/InspectionRecordDO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/inspection/InspectionRecordDO.java new file mode 100644 index 0000000..f255197 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/inspection/InspectionRecordDO.java @@ -0,0 +1,87 @@ +package cn.iocoder.yudao.module.asset.dal.dataobject.inspection; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.time.LocalDateTime; + +/** + * 验车记录 DO + * + * @author 芋道源码 + */ +@TableName("asset_inspection_record") +@KeySequence("asset_inspection_record_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InspectionRecordDO extends BaseDO { + + /** + * 主键ID + */ + @TableId + private Long id; + + /** + * 记录编码 + */ + private String recordCode; + + /** + * 模板ID + */ + private Long templateId; + + /** + * 来源类型(1=备车 2=交车 3=还车) + */ + private Integer sourceType; + + /** + * 来源ID + */ + private Long sourceId; + + /** + * 车辆ID + */ + private Long vehicleId; + + /** + * 检查人 + */ + private String inspectorName; + + /** + * 检查时间 + */ + private LocalDateTime inspectionTime; + + /** + * 状态(0=待检 1=检查中 2=已完成) + */ + private Integer status; + + /** + * 总体结果(1=通过 2=不通过 3=不适用) + */ + private Integer overallResult; + + /** + * 备注 + */ + private String remark; + + /** + * 克隆来源记录ID + */ + private Long clonedFromId; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/inspection/InspectionRecordItemDO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/inspection/InspectionRecordItemDO.java new file mode 100644 index 0000000..5a2d5ad --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/inspection/InspectionRecordItemDO.java @@ -0,0 +1,75 @@ +package cn.iocoder.yudao.module.asset.dal.dataobject.inspection; + +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_inspection_record_item") +@KeySequence("asset_inspection_record_item_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InspectionRecordItemDO extends BaseDO { + + /** + * 主键ID + */ + @TableId + private Long id; + + /** + * 记录ID + */ + private Long recordId; + + /** + * 检查项编码 + */ + private String itemCode; + + /** + * 分类 + */ + private String category; + + /** + * 检查项名称 + */ + private String itemName; + + /** + * 输入类型 + */ + private String inputType; + + /** + * 检查结果(1=通过 2=不通过 3=不适用) + */ + private Integer result; + + /** + * 检查值 + */ + private String value; + + /** + * 备注 + */ + private String remark; + + /** + * 图片URL列表 + */ + private String imageUrls; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/inspection/InspectionTemplateDO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/inspection/InspectionTemplateDO.java new file mode 100644 index 0000000..a06c58e --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/inspection/InspectionTemplateDO.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.asset.dal.dataobject.inspection; + +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_inspection_template") +@KeySequence("asset_inspection_template_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InspectionTemplateDO extends BaseDO { + + /** + * 主键ID + */ + @TableId + private Long id; + + /** + * 模板编码 + */ + private String code; + + /** + * 模板名称 + */ + private String name; + + /** + * 业务类型(1=备车 2=交车 3=还车) + */ + private Integer bizType; + + /** + * 车辆类型 + */ + private String vehicleType; + + /** + * 状态(0=禁用 1=启用) + */ + private Integer status; + + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/inspection/InspectionTemplateItemDO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/inspection/InspectionTemplateItemDO.java new file mode 100644 index 0000000..3876ee5 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/inspection/InspectionTemplateItemDO.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.module.asset.dal.dataobject.inspection; + +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_inspection_template_item") +@KeySequence("asset_inspection_template_item_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InspectionTemplateItemDO extends BaseDO { + + /** + * 主键ID + */ + @TableId + private Long id; + + /** + * 模板ID + */ + private Long templateId; + + /** + * 分类 + */ + private String category; + + /** + * 检查项名称 + */ + private String itemName; + + /** + * 检查项编码 + */ + private String itemCode; + + /** + * 输入类型 + */ + private String inputType; + + /** + * 排序 + */ + private Integer sort; + + /** + * 是否必填(0=否 1=是) + */ + private Integer required; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/inspection/InspectionRecordItemMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/inspection/InspectionRecordItemMapper.java new file mode 100644 index 0000000..9015db6 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/inspection/InspectionRecordItemMapper.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.asset.dal.mysql.inspection; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.asset.dal.dataobject.inspection.InspectionRecordItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 验车记录检查项 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InspectionRecordItemMapper extends BaseMapperX { + + default List selectByRecordId(Long recordId) { + return selectList(new LambdaQueryWrapperX() + .eq(InspectionRecordItemDO::getRecordId, recordId) + .orderByAsc(InspectionRecordItemDO::getId)); + } + + default int deleteByRecordId(Long recordId) { + return delete(new LambdaQueryWrapperX() + .eq(InspectionRecordItemDO::getRecordId, recordId)); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/inspection/InspectionRecordMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/inspection/InspectionRecordMapper.java new file mode 100644 index 0000000..5985723 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/inspection/InspectionRecordMapper.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.asset.dal.mysql.inspection; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.asset.dal.dataobject.inspection.InspectionRecordDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 验车记录 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InspectionRecordMapper extends BaseMapperX { + + default InspectionRecordDO selectLatestByVehicleAndSourceType(Long vehicleId, Integer sourceType) { + return selectOne(new LambdaQueryWrapperX() + .eq(InspectionRecordDO::getVehicleId, vehicleId) + .eq(InspectionRecordDO::getSourceType, sourceType) + .eq(InspectionRecordDO::getStatus, 2) + .orderByDesc(InspectionRecordDO::getId) + .last("LIMIT 1")); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/inspection/InspectionTemplateItemMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/inspection/InspectionTemplateItemMapper.java new file mode 100644 index 0000000..81b624c --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/inspection/InspectionTemplateItemMapper.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.asset.dal.mysql.inspection; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.asset.dal.dataobject.inspection.InspectionTemplateItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 验车模板检查项 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InspectionTemplateItemMapper extends BaseMapperX { + + default List selectByTemplateId(Long templateId) { + return selectList(new LambdaQueryWrapperX() + .eq(InspectionTemplateItemDO::getTemplateId, templateId) + .orderByAsc(InspectionTemplateItemDO::getSort)); + } + + default int deleteByTemplateId(Long templateId) { + return delete(new LambdaQueryWrapperX() + .eq(InspectionTemplateItemDO::getTemplateId, templateId)); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/inspection/InspectionTemplateMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/inspection/InspectionTemplateMapper.java new file mode 100644 index 0000000..632fde6 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/inspection/InspectionTemplateMapper.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.asset.dal.mysql.inspection; + +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.inspection.vo.InspectionTemplatePageReqVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.inspection.InspectionTemplateDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 验车模板 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InspectionTemplateMapper extends BaseMapperX { + + default PageResult selectPage(InspectionTemplatePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(InspectionTemplateDO::getCode, reqVO.getCode()) + .likeIfPresent(InspectionTemplateDO::getName, reqVO.getName()) + .eqIfPresent(InspectionTemplateDO::getBizType, reqVO.getBizType()) + .eqIfPresent(InspectionTemplateDO::getStatus, reqVO.getStatus()) + .orderByDesc(InspectionTemplateDO::getId)); + } + + default InspectionTemplateDO selectByBizTypeAndVehicleType(Integer bizType, String vehicleType) { + return selectOne(new LambdaQueryWrapperX() + .eq(InspectionTemplateDO::getBizType, bizType) + .eqIfPresent(InspectionTemplateDO::getVehicleType, vehicleType) + .eq(InspectionTemplateDO::getStatus, 1) + .last("LIMIT 1")); + } + + default InspectionTemplateDO selectDefaultByBizType(Integer bizType) { + return selectOne(new LambdaQueryWrapperX() + .eq(InspectionTemplateDO::getBizType, bizType) + .isNull(InspectionTemplateDO::getVehicleType) + .eq(InspectionTemplateDO::getStatus, 1) + .last("LIMIT 1")); + } + +} 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 5b486d2..11fe9dc 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 @@ -23,4 +23,54 @@ public interface ErrorCodeConstants { // ========== 供应商管理 1-008-004-000 ========== ErrorCode SUPPLIER_NOT_EXISTS = new ErrorCode(1_008_004_000, "供应商不存在"); + // ========== 车辆租赁合同管理 1-008-005-000 ========== + ErrorCode CONTRACT_NOT_EXISTS = new ErrorCode(1_008_005_000, "合同不存在"); + ErrorCode CONTRACT_CODE_DUPLICATE = new ErrorCode(1_008_005_001, "合同编码已存在"); + ErrorCode CONTRACT_STATUS_NOT_ALLOW_UPDATE = new ErrorCode(1_008_005_002, "当前合同状态不允许修改"); + ErrorCode CONTRACT_STATUS_NOT_ALLOW_DELETE = new ErrorCode(1_008_005_003, "当前合同状态不允许删除"); + ErrorCode CONTRACT_STATUS_NOT_ALLOW_SUBMIT = new ErrorCode(1_008_005_004, "当前合同状态不允许提交审批"); + ErrorCode CONTRACT_STATUS_NOT_ALLOW_WITHDRAW = new ErrorCode(1_008_005_005, "当前合同状态不允许撤回"); + ErrorCode CONTRACT_STATUS_NOT_ALLOW_TERMINATE = new ErrorCode(1_008_005_006, "当前合同状态不允许终止"); + ErrorCode CONTRACT_STATUS_NOT_ALLOW_RENEW = new ErrorCode(1_008_005_007, "当前合同状态不允许续签"); + ErrorCode CONTRACT_END_DATE_BEFORE_START_DATE = new ErrorCode(1_008_005_008, "合同结束日期不能早于开始日期"); + ErrorCode CONTRACT_VEHICLE_TIME_CONFLICT = new ErrorCode(1_008_005_009, "该车辆在此时间段内已有有效合同"); + ErrorCode CONTRACT_STATUS_NOT_ALLOW_CONVERT = new ErrorCode(1_008_005_010, "当前合同状态不允许变更"); + ErrorCode CONTRACT_STATUS_NOT_ALLOW_ADD_VEHICLE = new ErrorCode(1_008_005_011, "当前合同状态不允许新增车辆"); + ErrorCode CONTRACT_TYPE_NOT_TRIAL = new ErrorCode(1_008_005_012, "只有试用合同才能转正式"); + + // ========== 车辆登记 1-008-006-000 ========== + ErrorCode VEHICLE_REGISTRATION_NOT_EXISTS = new ErrorCode(1_008_006_000, "车辆登记不存在"); + + // ========== 备车管理 1-008-007-000 ========== + ErrorCode VEHICLE_PREPARE_NOT_EXISTS = new ErrorCode(1_008_007_000, "备车记录不存在"); + ErrorCode VEHICLE_PREPARE_ALREADY_COMPLETED = new ErrorCode(1_008_007_001, "备车记录已完成,不允许修改"); + + // ========== 交车任务管理 1-008-008-000 ========== + ErrorCode DELIVERY_TASK_NOT_EXISTS = new ErrorCode(1_008_008_000, "交车任务不存在"); + ErrorCode DELIVERY_TASK_ALREADY_DELIVERED = new ErrorCode(1_008_008_001, "交车任务已完成交车"); + ErrorCode DELIVERY_TASK_SUSPENDED = new ErrorCode(1_008_008_002, "交车任务已挂起"); + + // ========== 交车单管理 1-008-009-000 ========== + ErrorCode DELIVERY_ORDER_NOT_EXISTS = new ErrorCode(1_008_009_000, "交车单不存在"); + ErrorCode DELIVERY_ORDER_ALREADY_COMPLETED = new ErrorCode(1_008_009_001, "交车单已完成"); + + // ========== 还车单管理 1-008-010-000 ========== + ErrorCode RETURN_ORDER_NOT_EXISTS = new ErrorCode(1_008_010_000, "还车单不存在"); + ErrorCode RETURN_ORDER_ALREADY_SETTLED = new ErrorCode(1_008_010_001, "还车单已结算"); + + // ========== 验车模板管理 1-008-011-000 ========== + ErrorCode INSPECTION_TEMPLATE_NOT_EXISTS = new ErrorCode(1_008_011_000, "验车模板不存在"); + ErrorCode INSPECTION_RECORD_NOT_EXISTS = new ErrorCode(1_008_011_001, "验车记录不存在"); + ErrorCode INSPECTION_RECORD_ALREADY_COMPLETED = new ErrorCode(1_008_011_002, "验车记录已完成"); + ErrorCode INSPECTION_RECORD_REQUIRED_ITEMS_INCOMPLETE = new ErrorCode(1_008_011_003, "必填检查项未全部完成"); + ErrorCode INSPECTION_TEMPLATE_MATCH_FAILED = new ErrorCode(1_008_011_004, "未找到匹配的验车模板"); + + // ========== 替换车管理 1-008-012-000 ========== + ErrorCode VEHICLE_REPLACEMENT_NOT_EXISTS = new ErrorCode(1_008_012_000, "替换车申请不存在"); + ErrorCode VEHICLE_REPLACEMENT_STATUS_NOT_ALLOW_UPDATE = new ErrorCode(1_008_012_001, "当前状态不允许修改"); + ErrorCode VEHICLE_REPLACEMENT_STATUS_NOT_ALLOW_DELETE = new ErrorCode(1_008_012_002, "当前状态不允许删除"); + ErrorCode VEHICLE_REPLACEMENT_STATUS_NOT_ALLOW_SUBMIT = new ErrorCode(1_008_012_003, "当前状态不允许提交审批"); + ErrorCode VEHICLE_REPLACEMENT_STATUS_NOT_ALLOW_WITHDRAW = new ErrorCode(1_008_012_004, "当前状态不允许撤回"); + ErrorCode VEHICLE_REPLACEMENT_STATUS_NOT_ALLOW_CONFIRM = new ErrorCode(1_008_012_005, "当前状态不允许确认换回"); + } diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/inspection/InspectionRecordService.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/inspection/InspectionRecordService.java new file mode 100644 index 0000000..5c1fd7e --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/inspection/InspectionRecordService.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.asset.service.inspection; + +import cn.iocoder.yudao.module.asset.controller.admin.inspection.vo.InspectionRecordDetailVO; +import cn.iocoder.yudao.module.asset.controller.admin.inspection.vo.InspectionRecordItemUpdateReqVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.inspection.InspectionRecordDO; + +import jakarta.validation.Valid; + +/** + * 验车记录 Service 接口 + * + * @author 芋道源码 + */ +public interface InspectionRecordService { + + /** + * 创建验车记录(根据模板生成检查项) + */ + Long createRecord(Long templateId, Integer sourceType, Long sourceId, Long vehicleId); + + /** + * 克隆验车记录(从已有记录克隆,保留结果数据) + */ + Long cloneRecord(Long sourceRecordId, Integer newSourceType, Long newSourceId); + + /** + * 更新验车记录检查项 + */ + void updateRecordItem(@Valid InspectionRecordItemUpdateReqVO updateReqVO); + + /** + * 完成验车记录 + */ + void completeRecord(Long recordId, String inspectorName); + + /** + * 获取验车记录详情 + */ + InspectionRecordDetailVO getRecordDetail(Long recordId); + + /** + * 获取最新已完成的验车记录 + */ + InspectionRecordDO getLatestRecord(Long vehicleId, Integer sourceType); + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/inspection/InspectionRecordServiceImpl.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/inspection/InspectionRecordServiceImpl.java new file mode 100644 index 0000000..5cc0b7a --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/inspection/InspectionRecordServiceImpl.java @@ -0,0 +1,267 @@ +package cn.iocoder.yudao.module.asset.service.inspection; + +import cn.iocoder.yudao.module.asset.controller.admin.inspection.vo.InspectionRecordDetailVO; +import cn.iocoder.yudao.module.asset.controller.admin.inspection.vo.InspectionRecordItemUpdateReqVO; +import cn.iocoder.yudao.module.asset.convert.inspection.InspectionConvert; +import cn.iocoder.yudao.module.asset.dal.dataobject.inspection.InspectionRecordDO; +import cn.iocoder.yudao.module.asset.dal.dataobject.inspection.InspectionRecordItemDO; +import cn.iocoder.yudao.module.asset.dal.dataobject.inspection.InspectionTemplateItemDO; +import cn.iocoder.yudao.module.asset.dal.mysql.inspection.InspectionRecordItemMapper; +import cn.iocoder.yudao.module.asset.dal.mysql.inspection.InspectionRecordMapper; +import cn.iocoder.yudao.module.asset.dal.mysql.inspection.InspectionTemplateItemMapper; +import cn.iocoder.yudao.module.asset.enums.inspection.InspectionSourceTypeEnum; +import cn.iocoder.yudao.module.asset.enums.inspection.InspectionStatusEnum; +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.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.asset.enums.ErrorCodeConstants.*; + +/** + * 验车记录 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +@Slf4j +public class InspectionRecordServiceImpl implements InspectionRecordService { + + @Resource + private InspectionRecordMapper inspectionRecordMapper; + + @Resource + private InspectionRecordItemMapper inspectionRecordItemMapper; + + @Resource + private InspectionTemplateItemMapper inspectionTemplateItemMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createRecord(Long templateId, Integer sourceType, Long sourceId, Long vehicleId) { + // 查询模板检查项 + List templateItems = inspectionTemplateItemMapper.selectByTemplateId(templateId); + + // 生成记录编码 + String recordCode = generateRecordCode(sourceType); + + // 创建验车记录 + InspectionRecordDO record = InspectionRecordDO.builder() + .recordCode(recordCode) + .templateId(templateId) + .sourceType(sourceType) + .sourceId(sourceId) + .vehicleId(vehicleId) + .status(InspectionStatusEnum.PENDING.getStatus()) + .build(); + inspectionRecordMapper.insert(record); + + // 批量插入检查项(从模板复制) + if (!templateItems.isEmpty()) { + List recordItems = new ArrayList<>(templateItems.size()); + for (InspectionTemplateItemDO templateItem : templateItems) { + InspectionRecordItemDO recordItem = InspectionRecordItemDO.builder() + .recordId(record.getId()) + .itemCode(templateItem.getItemCode()) + .category(templateItem.getCategory()) + .itemName(templateItem.getItemName()) + .inputType(templateItem.getInputType()) + .build(); + recordItems.add(recordItem); + } + inspectionRecordItemMapper.insertBatch(recordItems); + } + + return record.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long cloneRecord(Long sourceRecordId, Integer newSourceType, Long newSourceId) { + // 查询源记录 + InspectionRecordDO sourceRecord = inspectionRecordMapper.selectById(sourceRecordId); + if (sourceRecord == null) { + throw exception(INSPECTION_RECORD_NOT_EXISTS); + } + + // 查询源检查项 + List sourceItems = inspectionRecordItemMapper.selectByRecordId(sourceRecordId); + + // 生成记录编码 + String recordCode = generateRecordCode(newSourceType); + + // 创建新记录 + InspectionRecordDO newRecord = InspectionRecordDO.builder() + .recordCode(recordCode) + .templateId(sourceRecord.getTemplateId()) + .sourceType(newSourceType) + .sourceId(newSourceId) + .vehicleId(sourceRecord.getVehicleId()) + .status(InspectionStatusEnum.PENDING.getStatus()) + .clonedFromId(sourceRecordId) + .build(); + inspectionRecordMapper.insert(newRecord); + + // 复制检查项(保留结果数据) + if (!sourceItems.isEmpty()) { + List newItems = new ArrayList<>(sourceItems.size()); + for (InspectionRecordItemDO sourceItem : sourceItems) { + InspectionRecordItemDO newItem = InspectionRecordItemDO.builder() + .recordId(newRecord.getId()) + .itemCode(sourceItem.getItemCode()) + .category(sourceItem.getCategory()) + .itemName(sourceItem.getItemName()) + .inputType(sourceItem.getInputType()) + .result(sourceItem.getResult()) + .value(sourceItem.getValue()) + .remark(sourceItem.getRemark()) + .imageUrls(sourceItem.getImageUrls()) + .build(); + newItems.add(newItem); + } + inspectionRecordItemMapper.insertBatch(newItems); + } + + return newRecord.getId(); + } + + @Override + public void updateRecordItem(InspectionRecordItemUpdateReqVO updateReqVO) { + // 校验检查项存在 + InspectionRecordItemDO item = inspectionRecordItemMapper.selectById(updateReqVO.getId()); + if (item == null) { + throw exception(INSPECTION_RECORD_NOT_EXISTS); + } + + // 更新检查项 + InspectionRecordItemDO updateObj = InspectionRecordItemDO.builder() + .id(updateReqVO.getId()) + .result(updateReqVO.getResult()) + .value(updateReqVO.getValue()) + .remark(updateReqVO.getRemark()) + .imageUrls(updateReqVO.getImageUrls()) + .build(); + inspectionRecordItemMapper.updateById(updateObj); + + // 如果记录状态为待检,更新为检查中 + InspectionRecordDO record = inspectionRecordMapper.selectById(item.getRecordId()); + if (record != null && InspectionStatusEnum.PENDING.getStatus().equals(record.getStatus())) { + InspectionRecordDO updateRecord = InspectionRecordDO.builder() + .id(record.getId()) + .status(InspectionStatusEnum.IN_PROGRESS.getStatus()) + .build(); + inspectionRecordMapper.updateById(updateRecord); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void completeRecord(Long recordId, String inspectorName) { + // 校验记录存在 + InspectionRecordDO record = inspectionRecordMapper.selectById(recordId); + if (record == null) { + throw exception(INSPECTION_RECORD_NOT_EXISTS); + } + + // 校验未完成 + if (InspectionStatusEnum.COMPLETED.getStatus().equals(record.getStatus())) { + throw exception(INSPECTION_RECORD_ALREADY_COMPLETED); + } + + // 校验必填项是否全部完成 + List items = inspectionRecordItemMapper.selectByRecordId(recordId); + // 查询模板检查项获取必填信息 + List templateItems = inspectionTemplateItemMapper.selectByTemplateId(record.getTemplateId()); + for (InspectionTemplateItemDO templateItem : templateItems) { + if (Integer.valueOf(1).equals(templateItem.getRequired())) { + // 查找对应的记录检查项 + boolean hasResult = items.stream() + .filter(item -> item.getItemCode().equals(templateItem.getItemCode())) + .anyMatch(item -> item.getResult() != null); + if (!hasResult) { + throw exception(INSPECTION_RECORD_REQUIRED_ITEMS_INCOMPLETE); + } + } + } + + // 计算总体结果:如果有任一不通过则整体不通过,否则通过 + Integer overallResult = 1; // 默认通过 + for (InspectionRecordItemDO item : items) { + if (item.getResult() != null && item.getResult() == 2) { + overallResult = 2; // 不通过 + break; + } + } + + // 更新记录状态 + InspectionRecordDO updateRecord = InspectionRecordDO.builder() + .id(recordId) + .status(InspectionStatusEnum.COMPLETED.getStatus()) + .inspectorName(inspectorName) + .inspectionTime(LocalDateTime.now()) + .overallResult(overallResult) + .build(); + inspectionRecordMapper.updateById(updateRecord); + } + + @Override + public InspectionRecordDetailVO getRecordDetail(Long recordId) { + InspectionRecordDO record = inspectionRecordMapper.selectById(recordId); + if (record == null) { + return null; + } + + InspectionRecordDetailVO detailVO = InspectionConvert.INSTANCE.convertRecordDetail(record); + + // 查询检查项 + List items = inspectionRecordItemMapper.selectByRecordId(recordId); + detailVO.setItems(InspectionConvert.INSTANCE.convertRecordItemVOList(items)); + + return detailVO; + } + + @Override + public InspectionRecordDO getLatestRecord(Long vehicleId, Integer sourceType) { + return inspectionRecordMapper.selectLatestByVehicleAndSourceType(vehicleId, sourceType); + } + + /** + * 生成记录编码 + * 格式: {BC|JC|HC}-yyyyMMdd-{seq} + */ + private String generateRecordCode(Integer sourceType) { + String prefix; + InspectionSourceTypeEnum sourceTypeEnum = InspectionSourceTypeEnum.valueOf(sourceType); + if (sourceTypeEnum == null) { + prefix = "YC"; + } else { + switch (sourceTypeEnum) { + case PREPARE: + prefix = "BC"; + break; + case DELIVERY: + prefix = "JC"; + break; + case RETURN: + prefix = "HC"; + break; + default: + prefix = "YC"; + } + } + + String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); + int seq = ThreadLocalRandom.current().nextInt(100, 999); + return prefix + "-" + dateStr + "-" + String.format("%03d", seq); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/inspection/InspectionTemplateService.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/inspection/InspectionTemplateService.java new file mode 100644 index 0000000..e9bf5bb --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/inspection/InspectionTemplateService.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.asset.service.inspection; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.asset.controller.admin.inspection.vo.InspectionTemplatePageReqVO; +import cn.iocoder.yudao.module.asset.controller.admin.inspection.vo.InspectionTemplateSaveReqVO; +import cn.iocoder.yudao.module.asset.controller.admin.inspection.vo.InspectionTemplateRespVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.inspection.InspectionTemplateDO; + +import jakarta.validation.Valid; + +/** + * 验车模板 Service 接口 + * + * @author 芋道源码 + */ +public interface InspectionTemplateService { + + /** + * 创建验车模板 + */ + Long createTemplate(@Valid InspectionTemplateSaveReqVO createReqVO); + + /** + * 更新验车模板 + */ + void updateTemplate(@Valid InspectionTemplateSaveReqVO updateReqVO); + + /** + * 删除验车模板 + */ + void deleteTemplate(Long id); + + /** + * 获取验车模板详情(含检查项) + */ + InspectionTemplateRespVO getTemplate(Long id); + + /** + * 获取验车模板分页 + */ + PageResult getTemplatePage(InspectionTemplatePageReqVO pageReqVO); + + /** + * 匹配验车模板 + * 优先精确匹配 bizType + vehicleType,其次匹配 bizType + vehicleType IS NULL 的默认模板 + */ + InspectionTemplateDO matchTemplate(Integer bizType, String vehicleType); + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/inspection/InspectionTemplateServiceImpl.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/inspection/InspectionTemplateServiceImpl.java new file mode 100644 index 0000000..911f175 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/inspection/InspectionTemplateServiceImpl.java @@ -0,0 +1,126 @@ +package cn.iocoder.yudao.module.asset.service.inspection; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.asset.controller.admin.inspection.vo.InspectionTemplatePageReqVO; +import cn.iocoder.yudao.module.asset.controller.admin.inspection.vo.InspectionTemplateSaveReqVO; +import cn.iocoder.yudao.module.asset.controller.admin.inspection.vo.InspectionTemplateRespVO; +import cn.iocoder.yudao.module.asset.convert.inspection.InspectionConvert; +import cn.iocoder.yudao.module.asset.dal.dataobject.inspection.InspectionTemplateDO; +import cn.iocoder.yudao.module.asset.dal.dataobject.inspection.InspectionTemplateItemDO; +import cn.iocoder.yudao.module.asset.dal.mysql.inspection.InspectionTemplateItemMapper; +import cn.iocoder.yudao.module.asset.dal.mysql.inspection.InspectionTemplateMapper; +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.*; + +/** + * 验车模板 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +@Slf4j +public class InspectionTemplateServiceImpl implements InspectionTemplateService { + + @Resource + private InspectionTemplateMapper inspectionTemplateMapper; + + @Resource + private InspectionTemplateItemMapper inspectionTemplateItemMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createTemplate(InspectionTemplateSaveReqVO createReqVO) { + // 插入模板 + InspectionTemplateDO template = InspectionConvert.INSTANCE.convert(createReqVO); + inspectionTemplateMapper.insert(template); + + // 插入检查项 + if (createReqVO.getItems() != null && !createReqVO.getItems().isEmpty()) { + List items = InspectionConvert.INSTANCE.convertItemList(createReqVO.getItems()); + items.forEach(item -> item.setTemplateId(template.getId())); + inspectionTemplateItemMapper.insertBatch(items); + } + return template.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateTemplate(InspectionTemplateSaveReqVO updateReqVO) { + // 校验存在 + validateTemplateExists(updateReqVO.getId()); + + // 更新模板 + InspectionTemplateDO updateObj = InspectionConvert.INSTANCE.convert(updateReqVO); + inspectionTemplateMapper.updateById(updateObj); + + // 删除旧检查项,插入新检查项 + inspectionTemplateItemMapper.deleteByTemplateId(updateReqVO.getId()); + if (updateReqVO.getItems() != null && !updateReqVO.getItems().isEmpty()) { + List items = InspectionConvert.INSTANCE.convertItemList(updateReqVO.getItems()); + items.forEach(item -> item.setTemplateId(updateReqVO.getId())); + inspectionTemplateItemMapper.insertBatch(items); + } + } + + @Override + public void deleteTemplate(Long id) { + // 校验存在 + validateTemplateExists(id); + // 删除模板 + inspectionTemplateMapper.deleteById(id); + // 删除检查项 + inspectionTemplateItemMapper.deleteByTemplateId(id); + } + + @Override + public InspectionTemplateRespVO getTemplate(Long id) { + InspectionTemplateDO template = inspectionTemplateMapper.selectById(id); + if (template == null) { + return null; + } + InspectionTemplateRespVO respVO = InspectionConvert.INSTANCE.convert(template); + // 查询检查项 + List items = inspectionTemplateItemMapper.selectByTemplateId(id); + respVO.setItems(InspectionConvert.INSTANCE.convertItemVOList(items)); + return respVO; + } + + @Override + public PageResult getTemplatePage(InspectionTemplatePageReqVO pageReqVO) { + return inspectionTemplateMapper.selectPage(pageReqVO); + } + + @Override + public InspectionTemplateDO matchTemplate(Integer bizType, String vehicleType) { + // 优先精确匹配 bizType + vehicleType + if (vehicleType != null) { + InspectionTemplateDO template = inspectionTemplateMapper.selectByBizTypeAndVehicleType(bizType, vehicleType); + if (template != null) { + return template; + } + } + // 其次匹配默认模板(vehicleType IS NULL) + InspectionTemplateDO defaultTemplate = inspectionTemplateMapper.selectDefaultByBizType(bizType); + if (defaultTemplate != null) { + return defaultTemplate; + } + throw exception(INSPECTION_TEMPLATE_MATCH_FAILED); + } + + private void validateTemplateExists(Long id) { + InspectionTemplateDO template = inspectionTemplateMapper.selectById(id); + if (template == null) { + throw exception(INSPECTION_TEMPLATE_NOT_EXISTS); + } + } + +}