feat(ai-report): 新增委托单位管理和报告审批功能
- 新增委托单位管理模块,支持增删改查、导入导出功能 - 实现委托单位 Excel 模板下载和数据导入功能 - 添加报告审批抽象处理器,支持审批流程日志记录 - 统一文件存储路径配置,将各模块独立路径改为统一根目录 - 新增 PQDIF 文件名存储字段,完善文件管理功能 - 修复代码中的乱码问题和错误提示信息 - 优化系统常量定义和字典配置管理
This commit is contained in:
@@ -11,8 +11,21 @@
|
||||
</parent>
|
||||
|
||||
<artifactId>test-report</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.njcn.gather</groupId>
|
||||
<artifactId>comservice</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.njcn.gather</groupId>
|
||||
<artifactId>report-model</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.njcn</groupId>
|
||||
<artifactId>njcn-common</artifactId>
|
||||
@@ -30,5 +43,27 @@
|
||||
<artifactId>spingboot2.3.12</artifactId>
|
||||
<version>2.3.12</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.njcn.gather</groupId>
|
||||
<artifactId>system</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.njcn.gather.aireport.testreport.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.njcn.common.pojo.annotation.OperateInfo;
|
||||
import com.njcn.common.pojo.constant.OperateType;
|
||||
import com.njcn.common.pojo.enums.common.LogEnum;
|
||||
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
|
||||
import com.njcn.common.pojo.response.HttpResult;
|
||||
import com.njcn.gather.aireport.testreport.pojo.param.TestReportParam;
|
||||
import com.njcn.gather.aireport.testreport.pojo.vo.TestReportVO;
|
||||
import com.njcn.gather.aireport.testreport.service.TestReportService;
|
||||
import com.njcn.web.controller.BaseController;
|
||||
import com.njcn.web.utils.HttpResultUtil;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "普测报告管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/test-report")
|
||||
@RequiredArgsConstructor
|
||||
public class TestReportController extends BaseController {
|
||||
|
||||
private final TestReportService testReportService;
|
||||
|
||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
|
||||
@ApiOperation("查询普测报告列表")
|
||||
@PostMapping("/list")
|
||||
public HttpResult<Page<TestReportVO>> list(@RequestBody(required = false) TestReportParam.QueryParam param) {
|
||||
String methodDescribe = getMethodDescribe("list");
|
||||
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS,
|
||||
testReportService.listTestReports(param), methodDescribe);
|
||||
}
|
||||
|
||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON, operateType = OperateType.ADD)
|
||||
@ApiOperation("新增普测报告")
|
||||
@PostMapping("/add")
|
||||
public HttpResult<Boolean> add(@RequestBody @Validated TestReportParam.AddParam param) {
|
||||
String methodDescribe = getMethodDescribe("add");
|
||||
boolean result = testReportService.addTestReport(param);
|
||||
return HttpResultUtil.assembleCommonResponseResult(result ? CommonResponseEnum.SUCCESS : CommonResponseEnum.FAIL,
|
||||
result, methodDescribe);
|
||||
}
|
||||
|
||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON, operateType = OperateType.UPDATE)
|
||||
@ApiOperation("编辑普测报告")
|
||||
@PostMapping("/update")
|
||||
public HttpResult<Boolean> update(@RequestBody @Validated TestReportParam.UpdateParam param) {
|
||||
String methodDescribe = getMethodDescribe("update");
|
||||
boolean result = testReportService.updateTestReport(param);
|
||||
return HttpResultUtil.assembleCommonResponseResult(result ? CommonResponseEnum.SUCCESS : CommonResponseEnum.FAIL,
|
||||
result, methodDescribe);
|
||||
}
|
||||
|
||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON, operateType = OperateType.DELETE)
|
||||
@ApiOperation("删除普测报告")
|
||||
@PostMapping("/delete")
|
||||
public HttpResult<Boolean> delete(@RequestBody List<String> ids) {
|
||||
String methodDescribe = getMethodDescribe("delete");
|
||||
boolean result = testReportService.deleteTestReports(ids);
|
||||
return HttpResultUtil.assembleCommonResponseResult(result ? CommonResponseEnum.SUCCESS : CommonResponseEnum.FAIL,
|
||||
result, methodDescribe);
|
||||
}
|
||||
|
||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
|
||||
@ApiOperation("查询普测报告详情")
|
||||
@ApiImplicitParam(name = "id", value = "普测报告ID", required = true)
|
||||
@GetMapping("/{id}")
|
||||
public HttpResult<TestReportVO> detail(@PathVariable("id") String id) {
|
||||
String methodDescribe = getMethodDescribe("detail");
|
||||
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS,
|
||||
testReportService.getTestReport(id), methodDescribe);
|
||||
}
|
||||
|
||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
|
||||
@ApiOperation("预览普测报告关联模板文件")
|
||||
@ApiImplicitParam(name = "id", value = "普测报告ID", required = true)
|
||||
@GetMapping("/{id}/preview")
|
||||
public ResponseEntity<byte[]> preview(@PathVariable("id") String id) {
|
||||
return testReportService.previewTemplate(id);
|
||||
}
|
||||
|
||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
|
||||
@ApiOperation("导出普测报告")
|
||||
@GetMapping("/export")
|
||||
public void export(@ModelAttribute TestReportParam.QueryParam param) {
|
||||
testReportService.exportTestReports(param);
|
||||
}
|
||||
|
||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON, operateType = OperateType.UPDATE)
|
||||
@ApiOperation("提交普测报告审核")
|
||||
@PostMapping("/submit-audit")
|
||||
public HttpResult<Boolean> submitAudit(@RequestBody @Validated TestReportParam.SubmitAuditParam param) {
|
||||
String methodDescribe = getMethodDescribe("submitAudit");
|
||||
boolean result = testReportService.submitAudit(param);
|
||||
return HttpResultUtil.assembleCommonResponseResult(result ? CommonResponseEnum.SUCCESS : CommonResponseEnum.FAIL,
|
||||
result, methodDescribe);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.njcn.gather.aireport.testreport.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.njcn.gather.aireport.testreport.pojo.param.TestReportParam;
|
||||
import com.njcn.gather.aireport.testreport.pojo.po.TestReportPO;
|
||||
import com.njcn.gather.aireport.testreport.pojo.vo.TestReportVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
@Mapper
|
||||
public interface TestReportMapper extends BaseMapper<TestReportPO> {
|
||||
|
||||
@Select({
|
||||
"<script>",
|
||||
"select r.id, r.no, r.client_unit_id as clientUnitId, cu.name as clientUnitName,",
|
||||
"r.report_model_id as reportModelId, rm.name as reportModelName, r.create_unit as createUnit,",
|
||||
"r.contract_number as contractNumber, r.standard, r.data, r.phonenumber, r.check_id as checkId,",
|
||||
"checker.name as checkerName, r.check_time as checkTime, r.check_result as checkResult, r.state,",
|
||||
"r.status, r.create_by as createBy, creator.name as createByName, r.create_time as createTime,",
|
||||
"r.update_by as updateBy, updater.name as updateByName, r.update_time as updateTime",
|
||||
"from ai_testreport r",
|
||||
"left join ai_clientunit cu on r.client_unit_id = cu.id",
|
||||
"left join ai_reportmodel rm on r.report_model_id = rm.id",
|
||||
"left join sys_user creator on r.create_by = creator.id",
|
||||
"left join sys_user updater on r.update_by = updater.id",
|
||||
"left join sys_user checker on r.check_id = checker.id",
|
||||
"where r.status = 1",
|
||||
"<if test='param.keyword != null and param.keyword != \"\"'>",
|
||||
"and (r.no like concat('%', #{param.keyword}, '%')",
|
||||
"or r.contract_number like concat('%', #{param.keyword}, '%')",
|
||||
"or cu.name like concat('%', #{param.keyword}, '%')",
|
||||
"or rm.name like concat('%', #{param.keyword}, '%'))",
|
||||
"</if>",
|
||||
"<if test='param.searchBeginTime != null and param.searchBeginTime != \"\"'>",
|
||||
"and r.create_time >= #{param.searchBeginTime}",
|
||||
"</if>",
|
||||
"<if test='param.searchEndTime != null and param.searchEndTime != \"\"'>",
|
||||
"and r.create_time <= #{param.searchEndTime}",
|
||||
"</if>",
|
||||
"<if test='param.state != null and param.state != \"\"'>",
|
||||
"and r.state = #{param.state}",
|
||||
"</if>",
|
||||
"order by r.create_time desc",
|
||||
"</script>"
|
||||
})
|
||||
Page<TestReportVO> selectReportPage(Page<TestReportVO> page, @Param("param") TestReportParam.QueryParam param);
|
||||
|
||||
@Select({
|
||||
"select r.id, r.no, r.client_unit_id as clientUnitId, cu.name as clientUnitName,",
|
||||
"r.report_model_id as reportModelId, rm.name as reportModelName, r.create_unit as createUnit,",
|
||||
"r.contract_number as contractNumber, r.standard, r.data, r.phonenumber, r.check_id as checkId,",
|
||||
"checker.name as checkerName, r.check_time as checkTime, r.check_result as checkResult, r.state,",
|
||||
"r.status, r.create_by as createBy, creator.name as createByName, r.create_time as createTime,",
|
||||
"r.update_by as updateBy, updater.name as updateByName, r.update_time as updateTime",
|
||||
"from ai_testreport r",
|
||||
"left join ai_clientunit cu on r.client_unit_id = cu.id",
|
||||
"left join ai_reportmodel rm on r.report_model_id = rm.id",
|
||||
"left join sys_user creator on r.create_by = creator.id",
|
||||
"left join sys_user updater on r.update_by = updater.id",
|
||||
"left join sys_user checker on r.check_id = checker.id",
|
||||
"where r.id = #{id} and r.status = 1"
|
||||
})
|
||||
TestReportVO selectReportDetail(@Param("id") String id);
|
||||
|
||||
@Select("select count(1) from ai_clientunit where id = #{id} and status = 1")
|
||||
int countNormalClientUnit(@Param("id") String id);
|
||||
|
||||
@Select("select count(1) from ai_reportmodel where id = #{id} and status = 1")
|
||||
int countNormalReportModel(@Param("id") String id);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.njcn.gather.aireport.testreport.pojo.constant;
|
||||
|
||||
public final class TestReportConst {
|
||||
|
||||
public static final String STATE_EDITING = "01";
|
||||
public static final String STATE_AUDITING = "02";
|
||||
public static final String STATE_APPROVED = "03";
|
||||
public static final String STATE_REJECTED = "04";
|
||||
public static final String STATE_DELETED = "05";
|
||||
|
||||
public static final Integer STATUS_DELETED = 0;
|
||||
public static final Integer STATUS_NORMAL = 1;
|
||||
|
||||
private TestReportConst() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.njcn.gather.aireport.testreport.pojo.param;
|
||||
|
||||
import com.njcn.web.pojo.param.BaseParam;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
public class TestReportParam {
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public static class QueryParam extends BaseParam {
|
||||
@ApiModelProperty("\u5173\u952e\u5b57\uff0c\u5339\u914d\u62a5\u544a\u7f16\u53f7\u3001\u5408\u540c\u7f16\u53f7\u3001\u59d4\u6258\u5355\u4f4d\u6216\u62a5\u544a\u6a21\u677f")
|
||||
private String keyword;
|
||||
|
||||
@ApiModelProperty("\u521b\u5efa\u5f00\u59cb\u65f6\u95f4\uff0cyyyy-MM-dd HH:mm:ss")
|
||||
private String searchBeginTime;
|
||||
|
||||
@ApiModelProperty("\u521b\u5efa\u7ed3\u675f\u65f6\u95f4\uff0cyyyy-MM-dd HH:mm:ss")
|
||||
private String searchEndTime;
|
||||
|
||||
@ApiModelProperty("\u62a5\u544a\u72b6\u6001")
|
||||
private String state;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class AddParam {
|
||||
@ApiModelProperty("\u666e\u6d4b\u62a5\u544a\u7f16\u53f7")
|
||||
@NotBlank(message = "\u666e\u6d4b\u62a5\u544a\u7f16\u53f7\u4e0d\u80fd\u4e3a\u7a7a")
|
||||
@Size(max = 32, message = "\u666e\u6d4b\u62a5\u544a\u7f16\u53f7\u4e0d\u80fd\u8d85\u8fc732\u4e2a\u5b57\u7b26")
|
||||
private String no;
|
||||
|
||||
@ApiModelProperty("\u59d4\u6258\u5355\u4f4dID")
|
||||
@NotBlank(message = "\u59d4\u6258\u5355\u4f4d\u4e0d\u80fd\u4e3a\u7a7a")
|
||||
private String clientUnitId;
|
||||
|
||||
@ApiModelProperty("\u62a5\u544a\u6a21\u677fID")
|
||||
@NotBlank(message = "\u62a5\u544a\u6a21\u677f\u4e0d\u80fd\u4e3a\u7a7a")
|
||||
private String reportModelId;
|
||||
|
||||
@ApiModelProperty("\u68c0\u6d4b\u516c\u53f8ID")
|
||||
@NotBlank(message = "\u68c0\u6d4b\u516c\u53f8\u4e0d\u80fd\u4e3a\u7a7a")
|
||||
private String createUnit;
|
||||
|
||||
@ApiModelProperty("\u5408\u540c\u7f16\u53f7")
|
||||
@NotBlank(message = "\u5408\u540c\u7f16\u53f7\u4e0d\u80fd\u4e3a\u7a7a")
|
||||
@Size(max = 32, message = "\u5408\u540c\u7f16\u53f7\u4e0d\u80fd\u8d85\u8fc732\u4e2a\u5b57\u7b26")
|
||||
private String contractNumber;
|
||||
|
||||
@ApiModelProperty("\u68c0\u6d4b\u4f9d\u636e\uff0cJSON\u5b57\u7b26\u4e32\u6570\u7ec4")
|
||||
@NotBlank(message = "\u68c0\u6d4b\u4f9d\u636e\u4e0d\u80fd\u4e3a\u7a7a")
|
||||
private String standard;
|
||||
|
||||
@ApiModelProperty("\u53d7\u8d44\u6570\u636e\uff0cJSON\u5bf9\u8c61\u6216JSON\u6570\u7ec4")
|
||||
@NotBlank(message = "\u53d7\u8d44\u6570\u636e\u4e0d\u80fd\u4e3a\u7a7a")
|
||||
private String data;
|
||||
|
||||
@ApiModelProperty("\u8054\u7cfb\u7535\u8bdd")
|
||||
@Size(max = 32, message = "\u8054\u7cfb\u7535\u8bdd\u4e0d\u80fd\u8d85\u8fc732\u4e2a\u5b57\u7b26")
|
||||
private String phonenumber;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class UpdateParam extends AddParam {
|
||||
@ApiModelProperty("\u666e\u6d4b\u62a5\u544aID")
|
||||
@NotBlank(message = "\u666e\u6d4b\u62a5\u544aID\u4e0d\u80fd\u4e3a\u7a7a")
|
||||
private String id;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class SubmitAuditParam {
|
||||
@ApiModelProperty("\u666e\u6d4b\u62a5\u544aID")
|
||||
@NotBlank(message = "\u666e\u6d4b\u62a5\u544aID\u4e0d\u80fd\u4e3a\u7a7a")
|
||||
private String id;
|
||||
|
||||
@ApiModelProperty("\u5ba1\u6838\u610f\u89c1")
|
||||
@Size(max = 128, message = "\u5ba1\u6838\u610f\u89c1\u4e0d\u80fd\u8d85\u8fc7128\u4e2a\u5b57\u7b26")
|
||||
private String checkResult;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.njcn.gather.aireport.testreport.pojo.po;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@TableName("ai_testreport")
|
||||
public class TestReportPO implements Serializable {
|
||||
private static final long serialVersionUID = -3038286126414044160L;
|
||||
|
||||
@TableId("id")
|
||||
private String id;
|
||||
@TableField("no")
|
||||
private String no;
|
||||
@TableField("client_unit_id")
|
||||
private String clientUnitId;
|
||||
@TableField("report_model_id")
|
||||
private String reportModelId;
|
||||
@TableField("create_unit")
|
||||
private String createUnit;
|
||||
@TableField("contract_number")
|
||||
private String contractNumber;
|
||||
@TableField("standard")
|
||||
private String standard;
|
||||
@TableField("data")
|
||||
private String data;
|
||||
@TableField("phonenumber")
|
||||
private String phonenumber;
|
||||
@TableField("state")
|
||||
private String state;
|
||||
@TableField("check_id")
|
||||
private String checkId;
|
||||
@TableField("check_time")
|
||||
private LocalDate checkTime;
|
||||
@TableField("check_result")
|
||||
private String checkResult;
|
||||
@TableField("status")
|
||||
private Integer status;
|
||||
@TableField("create_by")
|
||||
private String createBy;
|
||||
@TableField("create_time")
|
||||
private LocalDateTime createTime;
|
||||
@TableField("update_by")
|
||||
private String updateBy;
|
||||
@TableField("update_time")
|
||||
private LocalDateTime updateTime;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.njcn.gather.aireport.testreport.pojo.vo;
|
||||
|
||||
import cn.afterturn.easypoi.excel.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class TestReportExcelVO implements Serializable {
|
||||
private static final long serialVersionUID = -3010688465572795334L;
|
||||
|
||||
@Excel(name = "\u666e\u6d4b\u62a5\u544a\u7f16\u53f7", width = 25)
|
||||
private String no;
|
||||
|
||||
@Excel(name = "\u59d4\u6258\u5355\u4f4d", width = 25)
|
||||
private String clientUnitName;
|
||||
|
||||
@Excel(name = "\u62a5\u544a\u6a21\u677f", width = 25)
|
||||
private String reportModelName;
|
||||
|
||||
@Excel(name = "\u68c0\u6d4b\u516c\u53f8", width = 20)
|
||||
private String createUnit;
|
||||
|
||||
@Excel(name = "\u5408\u540c\u7f16\u53f7", width = 20)
|
||||
private String contractNumber;
|
||||
|
||||
@Excel(name = "\u68c0\u6d4b\u4f9d\u636e", width = 35)
|
||||
private String standard;
|
||||
|
||||
@Excel(name = "\u53d7\u8d44\u6570\u636e", width = 35)
|
||||
private String data;
|
||||
|
||||
@Excel(name = "\u8054\u7cfb\u7535\u8bdd", width = 20)
|
||||
private String phonenumber;
|
||||
|
||||
@Excel(name = "\u5ba1\u6838\u4eba", width = 20)
|
||||
private String checkerName;
|
||||
|
||||
@Excel(name = "\u5ba1\u6838\u65f6\u95f4", width = 20)
|
||||
private String checkTime;
|
||||
|
||||
@Excel(name = "\u5ba1\u6838\u610f\u89c1", width = 30)
|
||||
private String checkResult;
|
||||
|
||||
@Excel(name = "\u62a5\u544a\u72b6\u6001", width = 15)
|
||||
private String state;
|
||||
|
||||
@Excel(name = "\u521b\u5efa\u65f6\u95f4", width = 25)
|
||||
private String createTime;
|
||||
|
||||
@Excel(name = "\u521b\u5efa\u4eba", width = 20)
|
||||
private String createByName;
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package com.njcn.gather.aireport.testreport.pojo.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class TestReportVO {
|
||||
private static final String DEFAULT_EMPTY_DISPLAY = "-";
|
||||
|
||||
@ApiModelProperty("\u666e\u6d4b\u62a5\u544aID")
|
||||
private String id;
|
||||
@ApiModelProperty("\u666e\u6d4b\u62a5\u544a\u7f16\u53f7")
|
||||
private String no;
|
||||
@ApiModelProperty("\u59d4\u6258\u5355\u4f4dID")
|
||||
private String clientUnitId;
|
||||
@ApiModelProperty("\u59d4\u6258\u5355\u4f4d\u540d\u79f0")
|
||||
private String clientUnitName;
|
||||
@ApiModelProperty("\u62a5\u544a\u6a21\u677fID")
|
||||
private String reportModelId;
|
||||
@ApiModelProperty("\u62a5\u544a\u6a21\u677f\u540d\u79f0")
|
||||
private String reportModelName;
|
||||
@ApiModelProperty("\u68c0\u6d4b\u516c\u53f8ID")
|
||||
private String createUnit;
|
||||
@ApiModelProperty("\u5408\u540c\u7f16\u53f7")
|
||||
private String contractNumber;
|
||||
@ApiModelProperty("\u68c0\u6d4b\u4f9d\u636e")
|
||||
private String standard;
|
||||
@ApiModelProperty("\u53d7\u8d44\u6570\u636e")
|
||||
private String data;
|
||||
@ApiModelProperty("\u8054\u7cfb\u7535\u8bdd")
|
||||
private String phonenumber;
|
||||
@ApiModelProperty("\u5ba1\u6838\u4ebaID")
|
||||
private String checkId;
|
||||
@ApiModelProperty("\u5ba1\u6838\u4eba\u540d\u79f0")
|
||||
private String checkerName;
|
||||
@ApiModelProperty("\u5ba1\u6838\u65f6\u95f4")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@JsonDeserialize(using = LocalDateDeserializer.class)
|
||||
@JsonSerialize(using = LocalDateSerializer.class)
|
||||
private LocalDate checkTime;
|
||||
@ApiModelProperty("\u5ba1\u6838\u610f\u89c1")
|
||||
private String checkResult;
|
||||
@ApiModelProperty("\u62a5\u544a\u72b6\u6001")
|
||||
private String state;
|
||||
@ApiModelProperty("\u903b\u8f91\u72b6\u6001")
|
||||
private Integer status;
|
||||
@ApiModelProperty("\u521b\u5efa\u4eba\u663e\u793a\u540d")
|
||||
private String createBy;
|
||||
@ApiModelProperty("\u521b\u5efa\u4eba\u540d\u79f0")
|
||||
private String createByName;
|
||||
@ApiModelProperty("\u521b\u5efa\u65f6\u95f4")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
|
||||
@JsonSerialize(using = LocalDateTimeSerializer.class)
|
||||
private LocalDateTime createTime;
|
||||
@ApiModelProperty("\u66f4\u65b0\u4eba\u663e\u793a\u540d")
|
||||
private String updateBy;
|
||||
@ApiModelProperty("\u66f4\u65b0\u4eba\u540d\u79f0")
|
||||
private String updateByName;
|
||||
@ApiModelProperty("\u66f4\u65b0\u65f6\u95f4")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
|
||||
@JsonSerialize(using = LocalDateTimeSerializer.class)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
public String getId() {
|
||||
return defaultDisplay(id);
|
||||
}
|
||||
|
||||
public String getNo() {
|
||||
return defaultDisplay(no);
|
||||
}
|
||||
|
||||
public String getClientUnitId() {
|
||||
return defaultDisplay(clientUnitId);
|
||||
}
|
||||
|
||||
public String getClientUnitName() {
|
||||
return defaultDisplay(clientUnitName);
|
||||
}
|
||||
|
||||
public String getReportModelId() {
|
||||
return defaultDisplay(reportModelId);
|
||||
}
|
||||
|
||||
public String getReportModelName() {
|
||||
return defaultDisplay(reportModelName);
|
||||
}
|
||||
|
||||
public String getCreateUnit() {
|
||||
return defaultDisplay(createUnit);
|
||||
}
|
||||
|
||||
public String getContractNumber() {
|
||||
return defaultDisplay(contractNumber);
|
||||
}
|
||||
|
||||
public String getStandard() {
|
||||
return defaultDisplay(standard);
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return defaultDisplay(data);
|
||||
}
|
||||
|
||||
public String getPhonenumber() {
|
||||
return defaultDisplay(phonenumber);
|
||||
}
|
||||
|
||||
public String getCheckId() {
|
||||
return defaultDisplay(checkId);
|
||||
}
|
||||
|
||||
public String getCheckerName() {
|
||||
return defaultDisplay(checkerName);
|
||||
}
|
||||
|
||||
public String getCheckResult() {
|
||||
return defaultDisplay(checkResult);
|
||||
}
|
||||
|
||||
public String getState() {
|
||||
return defaultDisplay(state);
|
||||
}
|
||||
|
||||
public String getCreateBy() {
|
||||
return defaultDisplay(createBy);
|
||||
}
|
||||
|
||||
public String getCreateByName() {
|
||||
return defaultDisplay(createByName);
|
||||
}
|
||||
|
||||
public String getUpdateBy() {
|
||||
return defaultDisplay(updateBy);
|
||||
}
|
||||
|
||||
public String getUpdateByName() {
|
||||
return defaultDisplay(updateByName);
|
||||
}
|
||||
|
||||
private String defaultDisplay(String value) {
|
||||
return StringUtils.hasText(value) ? value : DEFAULT_EMPTY_DISPLAY;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.njcn.gather.aireport.testreport.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.njcn.gather.aireport.testreport.pojo.param.TestReportParam;
|
||||
import com.njcn.gather.aireport.testreport.pojo.po.TestReportPO;
|
||||
import com.njcn.gather.aireport.testreport.pojo.vo.TestReportVO;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface TestReportService extends IService<TestReportPO> {
|
||||
|
||||
Page<TestReportVO> listTestReports(TestReportParam.QueryParam param);
|
||||
|
||||
boolean addTestReport(TestReportParam.AddParam param);
|
||||
|
||||
boolean updateTestReport(TestReportParam.UpdateParam param);
|
||||
|
||||
boolean deleteTestReports(List<String> ids);
|
||||
|
||||
TestReportVO getTestReport(String id);
|
||||
|
||||
TestReportPO requireNormal(String id);
|
||||
|
||||
boolean submitAudit(TestReportParam.SubmitAuditParam param);
|
||||
|
||||
void exportTestReports(TestReportParam.QueryParam param);
|
||||
|
||||
ResponseEntity<byte[]> previewTemplate(String id);
|
||||
}
|
||||
@@ -0,0 +1,621 @@
|
||||
package com.njcn.gather.aireport.testreport.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
|
||||
import com.njcn.common.pojo.exception.BusinessException;
|
||||
import com.njcn.gather.aireport.reportmodel.component.ReportModelFileStorageService;
|
||||
import com.njcn.gather.aireport.reportmodel.pojo.po.ReportModelPO;
|
||||
import com.njcn.gather.aireport.reportmodel.service.ReportModelService;
|
||||
import com.njcn.gather.aireport.testreport.mapper.TestReportMapper;
|
||||
import com.njcn.gather.aireport.testreport.pojo.constant.TestReportConst;
|
||||
import com.njcn.gather.aireport.testreport.pojo.param.TestReportParam;
|
||||
import com.njcn.gather.aireport.testreport.pojo.po.TestReportPO;
|
||||
import com.njcn.gather.aireport.testreport.pojo.vo.TestReportExcelVO;
|
||||
import com.njcn.gather.aireport.testreport.pojo.vo.TestReportVO;
|
||||
import com.njcn.gather.aireport.testreport.service.TestReportService;
|
||||
import com.njcn.gather.comservice.filepreview.FilePreviewService;
|
||||
import com.njcn.gather.system.dictionary.pojo.po.DictData;
|
||||
import com.njcn.gather.system.dictionary.pojo.po.DictType;
|
||||
import com.njcn.gather.system.dictionary.service.IDictDataService;
|
||||
import com.njcn.gather.system.dictionary.service.IDictTypeService;
|
||||
import com.njcn.gather.system.pojo.constant.DictConst;
|
||||
import com.njcn.gather.system.util.ExportFileNameUtil;
|
||||
import com.njcn.web.factory.PageFactory;
|
||||
import com.njcn.web.utils.ExcelUtil;
|
||||
import com.njcn.web.utils.RequestUtil;
|
||||
import lombok.Data;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class TestReportServiceImpl extends ServiceImpl<TestReportMapper, TestReportPO> implements TestReportService {
|
||||
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
private static final Integer DICT_STATE_NORMAL = 1;
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
|
||||
private static final String MSG_ID_REQUIRED = "\u666e\u6d4b\u62a5\u544aID\u4e0d\u80fd\u4e3a\u7a7a";
|
||||
private static final String MSG_REPORT_NOT_FOUND = "\u666e\u6d4b\u62a5\u544a\u4e0d\u5b58\u5728\u6216\u5df2\u5220\u9664";
|
||||
private static final String MSG_ONLY_EDITABLE_CAN_UPDATE =
|
||||
"\u4ec5\u7f16\u5236\u6216\u9000\u56de\u72b6\u6001\u7684\u666e\u6d4b\u62a5\u544a\u5141\u8bb8\u7f16\u8f91";
|
||||
private static final String MSG_ONLY_EDITABLE_CAN_AUDIT =
|
||||
"\u4ec5\u7f16\u5236\u6216\u9000\u56de\u72b6\u6001\u7684\u666e\u6d4b\u62a5\u544a\u5141\u8bb8\u63d0\u4ea4\u5ba1\u6838";
|
||||
private static final String MSG_START_TIME_INVALID = "\u5f00\u59cb\u65f6\u95f4\u683c\u5f0f\u4e0d\u6b63\u786e";
|
||||
private static final String MSG_END_TIME_INVALID = "\u7ed3\u675f\u65f6\u95f4\u683c\u5f0f\u4e0d\u6b63\u786e";
|
||||
private static final String MSG_PARAM_REQUIRED = "\u666e\u6d4b\u62a5\u544a\u53c2\u6570\u4e0d\u80fd\u4e3a\u7a7a";
|
||||
private static final String MSG_NO_REQUIRED = "\u666e\u6d4b\u62a5\u544a\u7f16\u53f7\u4e0d\u80fd\u4e3a\u7a7a";
|
||||
private static final String MSG_NO_TOO_LONG = "\u666e\u6d4b\u62a5\u544a\u7f16\u53f7\u4e0d\u80fd\u8d85\u8fc732\u4e2a\u5b57\u7b26";
|
||||
private static final String MSG_CLIENT_UNIT_REQUIRED = "\u59d4\u6258\u5355\u4f4d\u4e0d\u80fd\u4e3a\u7a7a";
|
||||
private static final String MSG_REPORT_MODEL_REQUIRED = "\u62a5\u544a\u6a21\u677f\u4e0d\u80fd\u4e3a\u7a7a";
|
||||
private static final String MSG_CREATE_UNIT_REQUIRED = "\u68c0\u6d4b\u516c\u53f8\u4e0d\u80fd\u4e3a\u7a7a";
|
||||
private static final String MSG_CONTRACT_REQUIRED = "\u5408\u540c\u7f16\u53f7\u4e0d\u80fd\u4e3a\u7a7a";
|
||||
private static final String MSG_CONTRACT_TOO_LONG = "\u5408\u540c\u7f16\u53f7\u4e0d\u80fd\u8d85\u8fc732\u4e2a\u5b57\u7b26";
|
||||
private static final String MSG_STANDARD_REQUIRED = "\u68c0\u6d4b\u4f9d\u636e\u4e0d\u80fd\u4e3a\u7a7a";
|
||||
private static final String MSG_DATA_REQUIRED = "\u53d7\u8d44\u6570\u636e\u4e0d\u80fd\u4e3a\u7a7a";
|
||||
private static final String MSG_DATA_INVALID = "\u53d7\u8d44\u6570\u636e\u683c\u5f0f\u4e0d\u6b63\u786e";
|
||||
private static final String MSG_PHONE_TOO_LONG = "\u8054\u7cfb\u7535\u8bdd\u4e0d\u80fd\u8d85\u8fc732\u4e2a\u5b57\u7b26";
|
||||
private static final String MSG_NO_EXISTS = "\u666e\u6d4b\u62a5\u544a\u7f16\u53f7\u5df2\u5b58\u5728";
|
||||
private static final String MSG_COMPANY_NOT_FOUND = "\u68c0\u6d4b\u516c\u53f8\u4e0d\u5b58\u5728\u6216\u5df2\u5220\u9664";
|
||||
private static final String MSG_STANDARD_INVALID = "\u6d4b\u8bd5\u4f9d\u636e\u683c\u5f0f\u4e0d\u6b63\u786e";
|
||||
private static final String MSG_STANDARD_NOT_FOUND = "\u6d4b\u8bd5\u4f9d\u636e\u4e0d\u5b58\u5728\u6216\u5df2\u5220\u9664";
|
||||
private static final String MSG_CLIENT_UNIT_NOT_FOUND = "\u59d4\u6258\u5355\u4f4d\u4e0d\u5b58\u5728\u6216\u5df2\u5220\u9664";
|
||||
private static final String MSG_REPORT_MODEL_NOT_FOUND = "\u62a5\u544a\u6a21\u677f\u4e0d\u5b58\u5728\u6216\u5df2\u5220\u9664";
|
||||
private static final String MSG_PREVIEW_NOT_READY = "\u62a5\u544a\u6a21\u677f\u9884\u89c8\u670d\u52a1\u672a\u521d\u59cb\u5316";
|
||||
private static final String MSG_TEMPLATE_FILE_NOT_FOUND = "\u62a5\u544a\u6a21\u677f\u6587\u4ef6\u4e0d\u5b58\u5728";
|
||||
private static final String MSG_ENCODE_FILE_NAME_FAILED = "\u7f16\u7801\u62a5\u544a\u6a21\u677f\u6587\u4ef6\u540d\u5931\u8d25";
|
||||
|
||||
private final ReportModelService reportModelService;
|
||||
private final ReportModelFileStorageService reportModelFileStorageService;
|
||||
private final FilePreviewService filePreviewService;
|
||||
private final IDictTypeService dictTypeService;
|
||||
private final IDictDataService dictDataService;
|
||||
|
||||
public TestReportServiceImpl(ReportModelService reportModelService,
|
||||
ReportModelFileStorageService reportModelFileStorageService,
|
||||
FilePreviewService filePreviewService,
|
||||
IDictTypeService dictTypeService,
|
||||
IDictDataService dictDataService) {
|
||||
this.reportModelService = reportModelService;
|
||||
this.reportModelFileStorageService = reportModelFileStorageService;
|
||||
this.filePreviewService = filePreviewService;
|
||||
this.dictTypeService = dictTypeService;
|
||||
this.dictDataService = dictDataService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<TestReportVO> listTestReports(TestReportParam.QueryParam param) {
|
||||
TestReportParam.QueryParam query = normalizeQueryParam(param);
|
||||
Page<TestReportVO> page = this.baseMapper.selectReportPage(
|
||||
new Page<TestReportVO>(PageFactory.getPageNum(query), PageFactory.getPageSize(query)), query);
|
||||
fillDisplayUserNames(page.getRecords(), buildUserNameMap(page.getRecords()));
|
||||
fillDisplayFields(page.getRecords());
|
||||
return page;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean addTestReport(TestReportParam.AddParam param) {
|
||||
NormalizedReport data = normalizeParam(param);
|
||||
checkNoUnique(data.getNo(), null);
|
||||
checkClientUnit(data.getClientUnitId());
|
||||
checkReportModel(data.getReportModelId());
|
||||
checkCreateUnit(data.getCreateUnit());
|
||||
checkStandard(data.getStandard());
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
String userId = resolveCurrentUserId();
|
||||
TestReportPO report = new TestReportPO();
|
||||
report.setId(UUID.randomUUID().toString());
|
||||
applyBusinessFields(report, data);
|
||||
report.setState(TestReportConst.STATE_EDITING);
|
||||
report.setStatus(TestReportConst.STATUS_NORMAL);
|
||||
report.setCreateBy(userId);
|
||||
report.setCreateTime(now);
|
||||
report.setUpdateBy(userId);
|
||||
report.setUpdateTime(now);
|
||||
return this.save(report);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean updateTestReport(TestReportParam.UpdateParam param) {
|
||||
if (param == null || StrUtil.isBlank(param.getId())) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, MSG_ID_REQUIRED);
|
||||
}
|
||||
TestReportPO report = requireNormal(param.getId());
|
||||
if (!allowEdit(report.getState())) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, MSG_ONLY_EDITABLE_CAN_UPDATE);
|
||||
}
|
||||
NormalizedReport data = normalizeParam(param);
|
||||
checkNoUnique(data.getNo(), report.getId());
|
||||
checkClientUnit(data.getClientUnitId());
|
||||
checkReportModel(data.getReportModelId());
|
||||
checkCreateUnit(data.getCreateUnit());
|
||||
checkStandard(data.getStandard());
|
||||
|
||||
applyBusinessFields(report, data);
|
||||
report.setUpdateBy(resolveCurrentUserId());
|
||||
report.setUpdateTime(LocalDateTime.now());
|
||||
return this.updateById(report);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean deleteTestReports(List<String> ids) {
|
||||
List<String> validIds = normalizeIds(ids);
|
||||
if (validIds.isEmpty()) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, MSG_ID_REQUIRED);
|
||||
}
|
||||
return this.lambdaUpdate()
|
||||
.set(TestReportPO::getState, TestReportConst.STATE_DELETED)
|
||||
.set(TestReportPO::getStatus, TestReportConst.STATUS_DELETED)
|
||||
.set(TestReportPO::getUpdateBy, resolveCurrentUserId())
|
||||
.set(TestReportPO::getUpdateTime, LocalDateTime.now())
|
||||
.in(TestReportPO::getId, validIds)
|
||||
.eq(TestReportPO::getStatus, TestReportConst.STATUS_NORMAL)
|
||||
.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TestReportVO getTestReport(String id) {
|
||||
TestReportVO report = this.baseMapper.selectReportDetail(requireText(id, MSG_ID_REQUIRED));
|
||||
if (report == null) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, MSG_REPORT_NOT_FOUND);
|
||||
}
|
||||
fillDisplayUserNames(report, buildUserNameMap(Collections.singletonList(report)));
|
||||
fillDisplayFields(Collections.singletonList(report));
|
||||
return report;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TestReportPO requireNormal(String id) {
|
||||
String normalizedId = requireText(id, MSG_ID_REQUIRED);
|
||||
TestReportPO report = this.lambdaQuery()
|
||||
.eq(TestReportPO::getId, normalizedId)
|
||||
.eq(TestReportPO::getStatus, TestReportConst.STATUS_NORMAL)
|
||||
.one();
|
||||
if (report == null) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, MSG_REPORT_NOT_FOUND);
|
||||
}
|
||||
return report;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean submitAudit(TestReportParam.SubmitAuditParam param) {
|
||||
if (param == null || StrUtil.isBlank(param.getId())) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, MSG_ID_REQUIRED);
|
||||
}
|
||||
TestReportPO report = requireNormal(param.getId());
|
||||
if (!allowEdit(report.getState())) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, MSG_ONLY_EDITABLE_CAN_AUDIT);
|
||||
}
|
||||
report.setCheckId(null);
|
||||
report.setCheckTime(null);
|
||||
report.setCheckResult(null);
|
||||
report.setState(TestReportConst.STATE_AUDITING);
|
||||
report.setUpdateBy(resolveCurrentUserId());
|
||||
report.setUpdateTime(LocalDateTime.now());
|
||||
return this.updateById(report);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportTestReports(TestReportParam.QueryParam param) {
|
||||
TestReportParam.QueryParam query = normalizeQueryParam(param);
|
||||
Page<TestReportVO> page = this.baseMapper.selectReportPage(new Page<TestReportVO>(1, Integer.MAX_VALUE), query);
|
||||
fillDisplayUserNames(page.getRecords(), buildUserNameMap(page.getRecords()));
|
||||
fillDisplayFields(page.getRecords());
|
||||
List<TestReportExcelVO> exportRows = page.getRecords().stream()
|
||||
.map(this::toExcelVO)
|
||||
.collect(Collectors.toList());
|
||||
ExcelUtil.exportExcel(ExportFileNameUtil.appendToday("\u666e\u6d4b\u62a5\u544a\u5217\u8868.xlsx"),
|
||||
"\u666e\u6d4b\u62a5\u544a\u5217\u8868", TestReportExcelVO.class, exportRows);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<byte[]> previewTemplate(String id) {
|
||||
TestReportPO report = requireNormal(id);
|
||||
ReportModelPO model = requireReportModel(report.getReportModelId());
|
||||
Path filePath = reportModelFileStorageService.resolveDownloadPath(model.getPath());
|
||||
if (!Files.exists(filePath) || !Files.isRegularFile(filePath)) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, MSG_TEMPLATE_FILE_NOT_FOUND);
|
||||
}
|
||||
String fileName = resolvePreviewFileName(model);
|
||||
FilePreviewService.PreviewContent previewContent = filePreviewService.preview(filePath, fileName);
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename*=UTF-8''" + encodeFileName(fileName))
|
||||
.header(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, must-revalidate")
|
||||
.contentType(MediaType.parseMediaType(previewContent.getContentType()))
|
||||
.body(previewContent.getContent());
|
||||
}
|
||||
|
||||
private TestReportParam.QueryParam normalizeQueryParam(TestReportParam.QueryParam param) {
|
||||
TestReportParam.QueryParam query = param == null ? new TestReportParam.QueryParam() : param;
|
||||
query.setKeyword(trimToNull(query.getKeyword()));
|
||||
if (StrUtil.isNotBlank(query.getSearchBeginTime())) {
|
||||
query.setSearchBeginTime(formatDateTime(parseDateTime(query.getSearchBeginTime(), MSG_START_TIME_INVALID)));
|
||||
}
|
||||
if (StrUtil.isNotBlank(query.getSearchEndTime())) {
|
||||
query.setSearchEndTime(formatDateTime(parseDateTime(query.getSearchEndTime(), MSG_END_TIME_INVALID)));
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
private NormalizedReport normalizeParam(TestReportParam.AddParam param) {
|
||||
if (param == null) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, MSG_PARAM_REQUIRED);
|
||||
}
|
||||
NormalizedReport data = new NormalizedReport();
|
||||
data.setNo(requireText(param.getNo(), MSG_NO_REQUIRED, 32, MSG_NO_TOO_LONG));
|
||||
data.setClientUnitId(requireText(param.getClientUnitId(), MSG_CLIENT_UNIT_REQUIRED));
|
||||
data.setReportModelId(requireText(param.getReportModelId(), MSG_REPORT_MODEL_REQUIRED));
|
||||
data.setCreateUnit(requireText(param.getCreateUnit(), MSG_CREATE_UNIT_REQUIRED));
|
||||
data.setContractNumber(requireText(param.getContractNumber(), MSG_CONTRACT_REQUIRED, 32, MSG_CONTRACT_TOO_LONG));
|
||||
data.setStandard(requireText(param.getStandard(), MSG_STANDARD_REQUIRED));
|
||||
data.setData(requireJsonObjectOrArrayText(param.getData(), MSG_DATA_REQUIRED, MSG_DATA_INVALID));
|
||||
data.setPhonenumber(trimToNull(param.getPhonenumber()));
|
||||
if (data.getPhonenumber() != null && data.getPhonenumber().length() > 32) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, MSG_PHONE_TOO_LONG);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
private void applyBusinessFields(TestReportPO report, NormalizedReport data) {
|
||||
report.setNo(data.getNo());
|
||||
report.setClientUnitId(data.getClientUnitId());
|
||||
report.setReportModelId(data.getReportModelId());
|
||||
report.setCreateUnit(data.getCreateUnit());
|
||||
report.setContractNumber(data.getContractNumber());
|
||||
report.setStandard(data.getStandard());
|
||||
report.setData(data.getData());
|
||||
report.setPhonenumber(data.getPhonenumber());
|
||||
}
|
||||
|
||||
private boolean allowEdit(String state) {
|
||||
return TestReportConst.STATE_EDITING.equals(state) || TestReportConst.STATE_REJECTED.equals(state);
|
||||
}
|
||||
|
||||
private void checkNoUnique(String no, String excludeId) {
|
||||
LambdaQueryWrapper<TestReportPO> wrapper = new LambdaQueryWrapper<TestReportPO>();
|
||||
wrapper.eq(TestReportPO::getNo, no)
|
||||
.eq(TestReportPO::getStatus, TestReportConst.STATUS_NORMAL)
|
||||
.ne(StrUtil.isNotBlank(excludeId), TestReportPO::getId, excludeId);
|
||||
if (this.count(wrapper) > 0) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, MSG_NO_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
private TestReportExcelVO toExcelVO(TestReportVO vo) {
|
||||
TestReportExcelVO excelVO = new TestReportExcelVO();
|
||||
excelVO.setNo(vo.getNo());
|
||||
excelVO.setClientUnitName(StrUtil.isNotBlank(vo.getClientUnitName()) ? vo.getClientUnitName() : vo.getClientUnitId());
|
||||
excelVO.setReportModelName(StrUtil.isNotBlank(vo.getReportModelName()) ? vo.getReportModelName() : vo.getReportModelId());
|
||||
excelVO.setCreateUnit(vo.getCreateUnit());
|
||||
excelVO.setContractNumber(vo.getContractNumber());
|
||||
excelVO.setStandard(vo.getStandard());
|
||||
excelVO.setData(vo.getData());
|
||||
excelVO.setPhonenumber(vo.getPhonenumber());
|
||||
excelVO.setCheckerName(StrUtil.isNotBlank(vo.getCheckerName()) ? vo.getCheckerName() : vo.getCheckId());
|
||||
excelVO.setCheckTime(vo.getCheckTime() == null ? null : vo.getCheckTime().toString());
|
||||
excelVO.setCheckResult(vo.getCheckResult());
|
||||
excelVO.setState(vo.getState());
|
||||
excelVO.setCreateTime(vo.getCreateTime() == null ? null : DATE_TIME_FORMATTER.format(vo.getCreateTime()));
|
||||
excelVO.setCreateByName(StrUtil.isNotBlank(vo.getCreateByName()) ? vo.getCreateByName() : vo.getCreateBy());
|
||||
return excelVO;
|
||||
}
|
||||
|
||||
void fillDisplayUserNames(List<TestReportVO> reports, Map<String, String> userNameMap) {
|
||||
if (reports == null || reports.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (TestReportVO report : reports) {
|
||||
fillDisplayUserNames(report, userNameMap);
|
||||
}
|
||||
}
|
||||
|
||||
void fillDisplayUserNames(TestReportVO report, Map<String, String> userNameMap) {
|
||||
if (report == null) {
|
||||
return;
|
||||
}
|
||||
report.setCreateBy(resolveDisplayUserName(report.getCreateBy(), userNameMap));
|
||||
report.setUpdateBy(resolveDisplayUserName(report.getUpdateBy(), userNameMap));
|
||||
}
|
||||
|
||||
void fillDisplayFields(List<TestReportVO> reports) {
|
||||
if (reports == null || reports.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Map<String, String> companyNameMap = buildDictNameMap(DictConst.TEST_REPORT_COMPANY_DICT_CODE);
|
||||
Map<String, String> standardNameMap = buildDictNameMap(DictConst.TEST_REPORT_STANDARD_DICT_CODE);
|
||||
for (TestReportVO report : reports) {
|
||||
if (report == null) {
|
||||
continue;
|
||||
}
|
||||
report.setCreateUnit(resolveDictDisplayValue(report.getCreateUnit(), companyNameMap));
|
||||
report.setStandard(resolveStandardDisplayValue(report.getStandard(), standardNameMap));
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> buildUserNameMap(Collection<TestReportVO> reports) {
|
||||
if (reports == null || reports.isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<String, String> userNameMap = new LinkedHashMap<String, String>();
|
||||
for (TestReportVO report : reports) {
|
||||
if (report == null) {
|
||||
continue;
|
||||
}
|
||||
putUserName(userNameMap, report.getCreateBy(), report.getCreateByName());
|
||||
putUserName(userNameMap, report.getUpdateBy(), report.getUpdateByName());
|
||||
putUserName(userNameMap, report.getCheckId(), report.getCheckerName());
|
||||
}
|
||||
return userNameMap;
|
||||
}
|
||||
|
||||
private Map<String, String> buildDictNameMap(String typeCode) {
|
||||
if (dictTypeService == null || dictDataService == null || StrUtil.isBlank(typeCode)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
DictType dictType = dictTypeService.getByCode(typeCode);
|
||||
if (dictType == null || StrUtil.isBlank(dictType.getId()) || !DICT_STATE_NORMAL.equals(dictType.getState())) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
List<DictData> dictDataList = dictDataService.listDictDataByTypeId(dictType.getId());
|
||||
if (dictDataList == null || dictDataList.isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<String, String> result = new LinkedHashMap<String, String>();
|
||||
for (DictData dictData : dictDataList) {
|
||||
if (dictData == null || StrUtil.isBlank(dictData.getId()) || StrUtil.isBlank(dictData.getName())
|
||||
|| !DICT_STATE_NORMAL.equals(dictData.getState())) {
|
||||
continue;
|
||||
}
|
||||
result.put(dictData.getId(), dictData.getName());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void putUserName(Map<String, String> userNameMap, String userId, String userName) {
|
||||
String validUserId = trimToNull(userId);
|
||||
String validUserName = trimToNull(userName);
|
||||
if (validUserId == null || validUserName == null || "-".equals(validUserName)) {
|
||||
return;
|
||||
}
|
||||
userNameMap.put(validUserId, validUserName);
|
||||
}
|
||||
|
||||
private String resolveDisplayUserName(String userId, Map<String, String> userNameMap) {
|
||||
String validUserId = trimToNull(userId);
|
||||
if (validUserId == null) {
|
||||
return null;
|
||||
}
|
||||
if (userNameMap == null || userNameMap.isEmpty()) {
|
||||
return validUserId;
|
||||
}
|
||||
String userName = trimToNull(userNameMap.get(validUserId));
|
||||
return userName == null ? validUserId : userName;
|
||||
}
|
||||
|
||||
private String resolveDictDisplayValue(String rawValue, Map<String, String> dictNameMap) {
|
||||
String validValue = trimToNull(rawValue);
|
||||
if (validValue == null) {
|
||||
return null;
|
||||
}
|
||||
if (dictNameMap == null || dictNameMap.isEmpty()) {
|
||||
return validValue;
|
||||
}
|
||||
String displayValue = trimToNull(dictNameMap.get(validValue));
|
||||
return displayValue == null ? validValue : displayValue;
|
||||
}
|
||||
|
||||
private String resolveStandardDisplayValue(String rawValue, Map<String, String> dictNameMap) {
|
||||
String validValue = trimToNull(rawValue);
|
||||
if (validValue == null) {
|
||||
return null;
|
||||
}
|
||||
List<String> standardIds = parseJsonArray(validValue);
|
||||
if (standardIds.isEmpty()) {
|
||||
return validValue;
|
||||
}
|
||||
List<String> displayValues = new ArrayList<String>();
|
||||
for (String standardId : standardIds) {
|
||||
String displayValue = resolveDictDisplayValue(standardId, dictNameMap);
|
||||
if (displayValue != null) {
|
||||
displayValues.add(displayValue);
|
||||
}
|
||||
}
|
||||
if (displayValues.isEmpty()) {
|
||||
return validValue;
|
||||
}
|
||||
return String.join(", ", displayValues);
|
||||
}
|
||||
|
||||
private List<String> parseJsonArray(String jsonArrayText) {
|
||||
String text = trimToNull(jsonArrayText);
|
||||
if (text == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
try {
|
||||
List<String> parsedItems = OBJECT_MAPPER.readValue(text, new TypeReference<List<String>>() {
|
||||
});
|
||||
if (parsedItems == null || parsedItems.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<String> result = new ArrayList<String>();
|
||||
for (String item : parsedItems) {
|
||||
String normalizedItem = trimToNull(item);
|
||||
if (normalizedItem != null) {
|
||||
result.add(normalizedItem);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} catch (Exception exception) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
private String requireJsonObjectOrArrayText(String value, String blankMessage, String invalidMessage) {
|
||||
String text = requireText(value, blankMessage);
|
||||
try {
|
||||
JsonNode jsonNode = OBJECT_MAPPER.readTree(text);
|
||||
if (jsonNode == null || !(jsonNode.isObject() || jsonNode.isArray())) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, invalidMessage);
|
||||
}
|
||||
return text;
|
||||
} catch (BusinessException exception) {
|
||||
throw exception;
|
||||
} catch (Exception exception) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, invalidMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkCreateUnit(String createUnit) {
|
||||
Map<String, String> companyNameMap = buildDictNameMap(DictConst.TEST_REPORT_COMPANY_DICT_CODE);
|
||||
if (!companyNameMap.containsKey(createUnit)) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, MSG_COMPANY_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkStandard(String standard) {
|
||||
List<String> standardIds = parseJsonArray(standard);
|
||||
if (standardIds.isEmpty()) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, MSG_STANDARD_INVALID);
|
||||
}
|
||||
Map<String, String> standardNameMap = buildDictNameMap(DictConst.TEST_REPORT_STANDARD_DICT_CODE);
|
||||
for (String standardId : standardIds) {
|
||||
if (!standardNameMap.containsKey(standardId)) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, MSG_STANDARD_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkClientUnit(String id) {
|
||||
if (this.baseMapper.countNormalClientUnit(id) <= 0) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, MSG_CLIENT_UNIT_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkReportModel(String id) {
|
||||
if (this.baseMapper.countNormalReportModel(id) <= 0) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, MSG_REPORT_MODEL_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
private ReportModelPO requireReportModel(String id) {
|
||||
if (reportModelService == null || reportModelFileStorageService == null || filePreviewService == null) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, MSG_PREVIEW_NOT_READY);
|
||||
}
|
||||
return reportModelService.requireNormal(id);
|
||||
}
|
||||
|
||||
private String resolvePreviewFileName(ReportModelPO model) {
|
||||
String fileName = trimToNull(model.getFileName());
|
||||
if (fileName != null) {
|
||||
return fileName;
|
||||
}
|
||||
return reportModelFileStorageService.resolveDownloadFileName(model.getPath());
|
||||
}
|
||||
|
||||
private List<String> normalizeIds(List<String> ids) {
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<String> result = new ArrayList<String>();
|
||||
for (String id : ids) {
|
||||
String normalizedId = trimToNull(id);
|
||||
if (normalizedId != null && !result.contains(normalizedId)) {
|
||||
result.add(normalizedId);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private LocalDateTime parseDateTime(String value, String errorMessage) {
|
||||
try {
|
||||
return LocalDateTime.parse(value.trim(), DATE_TIME_FORMATTER);
|
||||
} catch (DateTimeParseException exception) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private String formatDateTime(LocalDateTime value) {
|
||||
return DATE_TIME_FORMATTER.format(value);
|
||||
}
|
||||
|
||||
private String requireText(String value, String blankMessage) {
|
||||
String text = trimToNull(value);
|
||||
if (text == null) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, blankMessage);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
private String requireText(String value, String blankMessage, int maxLength, String lengthMessage) {
|
||||
String text = requireText(value, blankMessage);
|
||||
if (text.length() > maxLength) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, lengthMessage);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
private String resolveCurrentUserId() {
|
||||
String userId = RequestUtil.getUserId();
|
||||
return StrUtil.isBlank(userId) ? null : userId;
|
||||
}
|
||||
|
||||
private String trimToNull(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String text = value.trim();
|
||||
if (text.isEmpty() || "-".equals(text)) {
|
||||
return null;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
private String encodeFileName(String fileName) {
|
||||
try {
|
||||
return URLEncoder.encode(fileName, StandardCharsets.UTF_8.name()).replace("+", "%20");
|
||||
} catch (Exception exception) {
|
||||
throw new BusinessException(CommonResponseEnum.FAIL, MSG_ENCODE_FILE_NAME_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
private static class NormalizedReport {
|
||||
private String no;
|
||||
private String clientUnitId;
|
||||
private String reportModelId;
|
||||
private String createUnit;
|
||||
private String contractNumber;
|
||||
private String standard;
|
||||
private String data;
|
||||
private String phonenumber;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.njcn.gather.aireport.testreport.pojo.vo;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
class TestReportVOTest {
|
||||
|
||||
@Test
|
||||
void getStateShouldUseDefaultDisplayWhenStateIsBlank() {
|
||||
TestReportVO report = new TestReportVO();
|
||||
|
||||
Assertions.assertEquals("-", report.getState());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getStateShouldReturnOriginalValueWhenStateExists() {
|
||||
TestReportVO report = new TestReportVO();
|
||||
report.setState("02");
|
||||
|
||||
Assertions.assertEquals("02", report.getState());
|
||||
}
|
||||
|
||||
@Test
|
||||
void timeJsonShouldUseConfiguredDateFormats() throws Exception {
|
||||
TestReportVO report = new TestReportVO();
|
||||
report.setCheckTime(LocalDate.of(2026, 6, 29));
|
||||
report.setCreateTime(LocalDateTime.of(2026, 6, 29, 9, 8, 7));
|
||||
report.setUpdateTime(LocalDateTime.of(2026, 6, 29, 18, 16, 14));
|
||||
|
||||
String json = new ObjectMapper().writeValueAsString(report);
|
||||
|
||||
Assertions.assertTrue(json.contains("\"checkTime\":\"2026-06-29\""));
|
||||
Assertions.assertTrue(json.contains("\"createTime\":\"2026-06-29 09:08:07\""));
|
||||
Assertions.assertTrue(json.contains("\"updateTime\":\"2026-06-29 18:16:14\""));
|
||||
Assertions.assertFalse(json.contains("2026-06-29T09"));
|
||||
Assertions.assertFalse(json.contains("2026-06-29T18"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
package com.njcn.gather.aireport.testreport.service.impl;
|
||||
|
||||
import com.njcn.common.pojo.exception.BusinessException;
|
||||
import com.njcn.gather.aireport.reportmodel.component.ReportModelFileStorageService;
|
||||
import com.njcn.gather.aireport.reportmodel.service.ReportModelService;
|
||||
import com.njcn.gather.aireport.testreport.pojo.constant.TestReportConst;
|
||||
import com.njcn.gather.aireport.testreport.pojo.param.TestReportParam;
|
||||
import com.njcn.gather.aireport.testreport.pojo.po.TestReportPO;
|
||||
import com.njcn.gather.aireport.testreport.pojo.vo.TestReportVO;
|
||||
import com.njcn.gather.comservice.filepreview.FilePreviewService;
|
||||
import com.njcn.gather.system.dictionary.pojo.po.DictData;
|
||||
import com.njcn.gather.system.dictionary.pojo.po.DictType;
|
||||
import com.njcn.gather.system.dictionary.service.IDictDataService;
|
||||
import com.njcn.gather.system.dictionary.service.IDictTypeService;
|
||||
import com.njcn.gather.system.pojo.constant.DictConst;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class TestReportServiceImplTest {
|
||||
|
||||
private static final Integer DICT_STATE_NORMAL = 1;
|
||||
private static final Integer DICT_STATE_DELETED = 0;
|
||||
|
||||
@Test
|
||||
void addTestReportShouldRejectMissingNo() {
|
||||
TestReportServiceImpl service = createService(mock(IDictTypeService.class), mock(IDictDataService.class));
|
||||
TestReportParam.AddParam param = new TestReportParam.AddParam();
|
||||
param.setClientUnitId("client-1");
|
||||
param.setReportModelId("model-1");
|
||||
param.setCreateUnit("unit-1");
|
||||
param.setContractNumber("HT-001");
|
||||
param.setStandard("[\"std-1\"]");
|
||||
param.setData("{}");
|
||||
|
||||
BusinessException exception = Assertions.assertThrows(BusinessException.class,
|
||||
() -> service.addTestReport(param));
|
||||
|
||||
Assertions.assertNotNull(exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void submitAuditShouldRejectMissingId() {
|
||||
TestReportServiceImpl service = createService(mock(IDictTypeService.class), mock(IDictDataService.class));
|
||||
TestReportParam.SubmitAuditParam param = new TestReportParam.SubmitAuditParam();
|
||||
param.setCheckResult("approved");
|
||||
|
||||
BusinessException exception = Assertions.assertThrows(BusinessException.class,
|
||||
() -> service.submitAudit(param));
|
||||
|
||||
Assertions.assertNotNull(exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void addTestReportShouldRejectInvalidStandardJsonArray() {
|
||||
TestReportServiceImpl service = createService(mock(IDictTypeService.class), mock(IDictDataService.class));
|
||||
TestReportParam.AddParam param = new TestReportParam.AddParam();
|
||||
param.setNo("PT-001");
|
||||
param.setClientUnitId("client-1");
|
||||
param.setReportModelId("model-1");
|
||||
param.setCreateUnit("company-1");
|
||||
param.setContractNumber("HT-001");
|
||||
param.setStandard("not-json-array");
|
||||
param.setData("{}");
|
||||
|
||||
BusinessException exception = Assertions.assertThrows(BusinessException.class,
|
||||
() -> service.addTestReport(param));
|
||||
|
||||
Assertions.assertTrue(exception.getMessage().contains("\u6d4b\u8bd5\u4f9d\u636e"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void addTestReportShouldRejectInvalidDataJson() {
|
||||
TestReportServiceImpl service = createService(mock(IDictTypeService.class), mock(IDictDataService.class));
|
||||
TestReportParam.AddParam param = buildValidNormalizeParam();
|
||||
param.setData("not-json");
|
||||
|
||||
BusinessException exception = Assertions.assertThrows(BusinessException.class,
|
||||
() -> invokeNormalizeParam(service, param));
|
||||
|
||||
Assertions.assertTrue(exception.getMessage().contains("\u6536\u8d44\u6570\u636e"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void addTestReportShouldRejectScalarDataJson() {
|
||||
TestReportServiceImpl service = createService(mock(IDictTypeService.class), mock(IDictDataService.class));
|
||||
TestReportParam.AddParam param = buildValidNormalizeParam();
|
||||
param.setData("\"plain-text\"");
|
||||
|
||||
BusinessException exception = Assertions.assertThrows(BusinessException.class,
|
||||
() -> invokeNormalizeParam(service, param));
|
||||
|
||||
Assertions.assertTrue(exception.getMessage().contains("\u6536\u8d44\u6570\u636e"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void normalizeParamShouldAcceptJsonObjectAndJsonArrayData() {
|
||||
TestReportServiceImpl service = createService(mock(IDictTypeService.class), mock(IDictDataService.class));
|
||||
TestReportParam.AddParam objectParam = buildValidNormalizeParam();
|
||||
objectParam.setData("{\"fileName\":\"report.json\"}");
|
||||
TestReportParam.AddParam arrayParam = buildValidNormalizeParam();
|
||||
arrayParam.setData("[{\"fileName\":\"report-a.json\"}]");
|
||||
|
||||
Assertions.assertDoesNotThrow(() -> invokeNormalizeParam(service, objectParam));
|
||||
Assertions.assertDoesNotThrow(() -> invokeNormalizeParam(service, arrayParam));
|
||||
}
|
||||
|
||||
@Test
|
||||
void addTestReportShouldRejectDeletedStandardDictData() {
|
||||
IDictTypeService dictTypeService = mock(IDictTypeService.class);
|
||||
IDictDataService dictDataService = mock(IDictDataService.class);
|
||||
TestReportServiceImpl service = createService(dictTypeService, dictDataService);
|
||||
mockNormalDictType(dictTypeService, DictConst.TEST_REPORT_COMPANY_DICT_CODE, "type-company");
|
||||
mockNormalDictType(dictTypeService, DictConst.TEST_REPORT_STANDARD_DICT_CODE, "type-standard");
|
||||
when(dictDataService.listDictDataByTypeId("type-company")).thenReturn(Collections.singletonList(
|
||||
buildDictData("company-1", "company-A", DICT_STATE_NORMAL)));
|
||||
when(dictDataService.listDictDataByTypeId("type-standard")).thenReturn(Collections.singletonList(
|
||||
buildDictData("std-1", "standard-A", DICT_STATE_DELETED)));
|
||||
TestReportParam.AddParam param = new TestReportParam.AddParam();
|
||||
param.setNo("PT-001");
|
||||
param.setClientUnitId("client-1");
|
||||
param.setReportModelId("model-1");
|
||||
param.setCreateUnit("company-1");
|
||||
param.setContractNumber("HT-001");
|
||||
param.setStandard("[\"std-1\"]");
|
||||
param.setData("{}");
|
||||
|
||||
BusinessException exception = Assertions.assertThrows(BusinessException.class,
|
||||
() -> service.addTestReport(param));
|
||||
|
||||
Assertions.assertTrue(exception.getMessage().contains("\u6d4b\u8bd5\u4f9d\u636e"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void fillDisplayUserNamesShouldPreferUserNameFallbackToUserIdAndDash() {
|
||||
TestReportServiceImpl service = createService(mock(IDictTypeService.class), mock(IDictDataService.class));
|
||||
TestReportVO first = new TestReportVO();
|
||||
first.setCreateBy("creator-001");
|
||||
first.setUpdateBy("updater-001");
|
||||
first.setCreateByName("creator-A");
|
||||
first.setUpdateByName("updater-A");
|
||||
TestReportVO second = new TestReportVO();
|
||||
second.setCreateBy("creator-002");
|
||||
second.setUpdateBy(null);
|
||||
|
||||
Map<String, String> userNameMap = new HashMap<String, String>();
|
||||
userNameMap.put("creator-001", "creator-A");
|
||||
userNameMap.put("updater-001", "updater-A");
|
||||
|
||||
service.fillDisplayUserNames(first, userNameMap);
|
||||
service.fillDisplayUserNames(second, userNameMap);
|
||||
|
||||
Assertions.assertEquals("creator-A", first.getCreateBy());
|
||||
Assertions.assertEquals("updater-A", first.getUpdateBy());
|
||||
Assertions.assertEquals("creator-002", second.getCreateBy());
|
||||
Assertions.assertEquals("-", second.getUpdateBy());
|
||||
}
|
||||
|
||||
@Test
|
||||
void fillDisplayFieldsShouldResolveDictNamesAndFallbackToRawValue() {
|
||||
IDictTypeService dictTypeService = mock(IDictTypeService.class);
|
||||
IDictDataService dictDataService = mock(IDictDataService.class);
|
||||
TestReportServiceImpl service = createService(dictTypeService, dictDataService);
|
||||
mockNormalDictType(dictTypeService, DictConst.TEST_REPORT_COMPANY_DICT_CODE, "type-company");
|
||||
mockNormalDictType(dictTypeService, DictConst.TEST_REPORT_STANDARD_DICT_CODE, "type-standard");
|
||||
when(dictDataService.listDictDataByTypeId("type-company")).thenReturn(Collections.singletonList(
|
||||
buildDictData("company-1", "Nanjing Zhiyou", DICT_STATE_NORMAL)));
|
||||
when(dictDataService.listDictDataByTypeId("type-standard")).thenReturn(Arrays.asList(
|
||||
buildDictData("std-1", "GB 50150-2016", DICT_STATE_NORMAL),
|
||||
buildDictData("std-2", "DL/T 596-2021", DICT_STATE_NORMAL)));
|
||||
TestReportVO first = new TestReportVO();
|
||||
first.setCreateUnit("company-1");
|
||||
first.setStandard("[\"std-1\",\"std-2\"]");
|
||||
TestReportVO second = new TestReportVO();
|
||||
second.setCreateUnit("company-unknown");
|
||||
second.setStandard("[\"std-unknown\"]");
|
||||
|
||||
service.fillDisplayFields(Arrays.asList(first, second));
|
||||
|
||||
Assertions.assertEquals("Nanjing Zhiyou", first.getCreateUnit());
|
||||
Assertions.assertEquals("GB 50150-2016, DL/T 596-2021", first.getStandard());
|
||||
Assertions.assertEquals("company-unknown", second.getCreateUnit());
|
||||
Assertions.assertEquals("std-unknown", second.getStandard());
|
||||
}
|
||||
|
||||
@Test
|
||||
void fillDisplayFieldsShouldIgnoreDeletedDictData() {
|
||||
IDictTypeService dictTypeService = mock(IDictTypeService.class);
|
||||
IDictDataService dictDataService = mock(IDictDataService.class);
|
||||
TestReportServiceImpl service = createService(dictTypeService, dictDataService);
|
||||
mockNormalDictType(dictTypeService, DictConst.TEST_REPORT_COMPANY_DICT_CODE, "type-company");
|
||||
mockNormalDictType(dictTypeService, DictConst.TEST_REPORT_STANDARD_DICT_CODE, "type-standard");
|
||||
when(dictDataService.listDictDataByTypeId("type-company")).thenReturn(Collections.singletonList(
|
||||
buildDictData("company-1", "company-A", DICT_STATE_DELETED)));
|
||||
when(dictDataService.listDictDataByTypeId("type-standard")).thenReturn(Collections.singletonList(
|
||||
buildDictData("std-1", "standard-A", DICT_STATE_DELETED)));
|
||||
TestReportVO report = new TestReportVO();
|
||||
report.setCreateUnit("company-1");
|
||||
report.setStandard("[\"std-1\"]");
|
||||
|
||||
service.fillDisplayFields(Collections.singletonList(report));
|
||||
|
||||
Assertions.assertEquals("company-1", report.getCreateUnit());
|
||||
Assertions.assertEquals("std-1", report.getStandard());
|
||||
}
|
||||
|
||||
@Test
|
||||
void submitAuditShouldMoveEditingStateToAuditingAndClearAuditFields() {
|
||||
TestReportPO report = new TestReportPO();
|
||||
report.setId("report-001");
|
||||
report.setState(TestReportConst.STATE_EDITING);
|
||||
report.setStatus(TestReportConst.STATUS_NORMAL);
|
||||
report.setCheckId("checker-001");
|
||||
report.setCheckTime(java.time.LocalDate.of(2026, 6, 26));
|
||||
report.setCheckResult("done");
|
||||
TestableTestReportServiceImpl service = new TestableTestReportServiceImpl(mock(IDictTypeService.class),
|
||||
mock(IDictDataService.class), report);
|
||||
TestReportParam.SubmitAuditParam param = new TestReportParam.SubmitAuditParam();
|
||||
param.setId("report-001");
|
||||
|
||||
boolean result = service.submitAudit(param);
|
||||
|
||||
Assertions.assertTrue(result);
|
||||
Assertions.assertEquals(TestReportConst.STATE_AUDITING, report.getState());
|
||||
Assertions.assertNull(report.getCheckId());
|
||||
Assertions.assertNull(report.getCheckTime());
|
||||
Assertions.assertNull(report.getCheckResult());
|
||||
Assertions.assertSame(report, service.updatedReport);
|
||||
}
|
||||
|
||||
private TestReportServiceImpl createService(IDictTypeService dictTypeService, IDictDataService dictDataService) {
|
||||
return new TestReportServiceImpl(
|
||||
mock(ReportModelService.class),
|
||||
mock(ReportModelFileStorageService.class),
|
||||
mock(FilePreviewService.class),
|
||||
dictTypeService,
|
||||
dictDataService);
|
||||
}
|
||||
|
||||
private TestReportParam.AddParam buildValidNormalizeParam() {
|
||||
TestReportParam.AddParam param = new TestReportParam.AddParam();
|
||||
param.setNo("PT-001");
|
||||
param.setClientUnitId("client-1");
|
||||
param.setReportModelId("model-1");
|
||||
param.setCreateUnit("company-1");
|
||||
param.setContractNumber("HT-001");
|
||||
param.setStandard("[\"std-1\"]");
|
||||
param.setData("{}");
|
||||
return param;
|
||||
}
|
||||
|
||||
private Object invokeNormalizeParam(TestReportServiceImpl service, TestReportParam.AddParam param) {
|
||||
try {
|
||||
Method method = TestReportServiceImpl.class.getDeclaredMethod("normalizeParam", TestReportParam.AddParam.class);
|
||||
method.setAccessible(true);
|
||||
return method.invoke(service, param);
|
||||
} catch (java.lang.reflect.InvocationTargetException exception) {
|
||||
Throwable targetException = exception.getTargetException();
|
||||
if (targetException instanceof RuntimeException) {
|
||||
throw (RuntimeException) targetException;
|
||||
}
|
||||
throw new RuntimeException(targetException);
|
||||
} catch (Exception exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
}
|
||||
|
||||
private static class TestableTestReportServiceImpl extends TestReportServiceImpl {
|
||||
private final TestReportPO report;
|
||||
private TestReportPO updatedReport;
|
||||
|
||||
private TestableTestReportServiceImpl(IDictTypeService dictTypeService, IDictDataService dictDataService,
|
||||
TestReportPO report) {
|
||||
super(mock(ReportModelService.class), mock(ReportModelFileStorageService.class),
|
||||
mock(FilePreviewService.class), dictTypeService, dictDataService);
|
||||
this.report = report;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TestReportPO requireNormal(String id) {
|
||||
return report;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateById(TestReportPO entity) {
|
||||
this.updatedReport = entity;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void mockNormalDictType(IDictTypeService dictTypeService, String code, String typeId) {
|
||||
when(dictTypeService.getByCode(code)).thenReturn(buildDictType(typeId, code));
|
||||
}
|
||||
|
||||
private DictType buildDictType(String id, String code) {
|
||||
DictType dictType = new DictType();
|
||||
dictType.setId(id);
|
||||
dictType.setCode(code);
|
||||
dictType.setState(DICT_STATE_NORMAL);
|
||||
return dictType;
|
||||
}
|
||||
|
||||
private DictData buildDictData(String id, String name, Integer state) {
|
||||
DictData dictData = new DictData();
|
||||
dictData.setId(id);
|
||||
dictData.setName(name);
|
||||
dictData.setState(state);
|
||||
return dictData;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user