feat(mms-mapping): 添加ICD校验结果保存功能支持文件上传
- 在CsIcdPathController中添加POST接口支持multipart表单上传ICD文件 - 实现saveIcdCheckResultWithFile方法处理文件上传和校验结果保存 - 添加fillIcdFile方法处理ICD文件内容填充到参数对象 - 在CsIcdPathPO中将Icd_Content字段重命名为Icd并使用JsonNodeTypeHandler处理JSON转换 - 更新resultMap配置使用新的字段映射关系 - 修改ICD一致性校验服务的日志记录和校验逻辑 - 移除自动修正映射差异的功能,只保留一致性检查 - 优化测试用例验证ICD校验结果保存和文件上传功能
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package com.njcn.gather.steady.checksquare.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.njcn.gather.steady.checksquare.component.SteadyChecksquareCalculator;
|
||||
@@ -32,8 +34,11 @@ import com.njcn.gather.tool.adddata.component.AddDataTimeSlotCalculator;
|
||||
import com.njcn.gather.tool.addledger.pojo.vo.AddLedgerLinePathVO;
|
||||
import com.njcn.gather.tool.addledger.service.AddLedgerService;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
||||
import org.apache.ibatis.session.Configuration;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
@@ -58,6 +63,14 @@ import static org.mockito.Mockito.when;
|
||||
* 鏁版嵁鏍¢獙鏈嶅姟娴嬭瘯銆? */
|
||||
class SteadyChecksquareServiceImplTest {
|
||||
|
||||
@BeforeAll
|
||||
static void initMybatisPlusTableInfo() {
|
||||
MapperBuilderAssistant assistant = new MapperBuilderAssistant(new Configuration(), "");
|
||||
TableInfoHelper.initTableInfo(assistant, SteadyChecksquareTaskPO.class);
|
||||
TableInfoHelper.initTableInfo(assistant, SteadyChecksquareItemPO.class);
|
||||
TableInfoHelper.initTableInfo(assistant, SteadyChecksquareDetailPO.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotOpenTransactionAroundCreateCalculation() throws Exception {
|
||||
Method createMethod = SteadyChecksquareServiceImpl.class.getMethod("create", SteadyChecksquareQueryParam.class);
|
||||
@@ -72,7 +85,7 @@ class SteadyChecksquareServiceImplTest {
|
||||
LambdaQueryChainWrapper<SteadyChecksquareTaskPO> taskQuery = mock(LambdaQueryChainWrapper.class);
|
||||
when(taskService.lambdaQuery()).thenReturn(taskQuery);
|
||||
when(taskQuery.eq(any(), any())).thenReturn(taskQuery);
|
||||
when(taskQuery.orderByDesc(any())).thenReturn(taskQuery);
|
||||
when(taskQuery.orderByDesc(any(SFunction.class))).thenReturn(taskQuery);
|
||||
when(taskQuery.list()).thenReturn(Collections.emptyList());
|
||||
SteadyChecksquareServiceImpl service = new SteadyChecksquareServiceImpl(new SteadyTrendIndicatorCatalog(),
|
||||
mock(SteadyChecksquareInfluxQueryComponent.class), new SteadyChecksquareCalculator(),
|
||||
@@ -110,7 +123,7 @@ class SteadyChecksquareServiceImplTest {
|
||||
LambdaQueryChainWrapper<SteadyChecksquareTaskPO> taskQuery = mock(LambdaQueryChainWrapper.class);
|
||||
when(taskService.lambdaQuery()).thenReturn(taskQuery);
|
||||
when(taskQuery.eq(any(), any())).thenReturn(taskQuery);
|
||||
when(taskQuery.orderByDesc(any())).thenReturn(taskQuery);
|
||||
when(taskQuery.orderByDesc(any(SFunction.class))).thenReturn(taskQuery);
|
||||
when(taskQuery.list()).thenReturn(Collections.emptyList());
|
||||
SteadyChecksquareServiceImpl service = new SteadyChecksquareServiceImpl(new SteadyTrendIndicatorCatalog(),
|
||||
influxQueryComponent, new SteadyChecksquareCalculator(),
|
||||
@@ -165,7 +178,7 @@ class SteadyChecksquareServiceImplTest {
|
||||
task.setState(1);
|
||||
when(taskService.lambdaQuery()).thenReturn(taskQuery);
|
||||
when(taskQuery.eq(any(), any())).thenReturn(taskQuery);
|
||||
when(taskQuery.orderByDesc(any())).thenReturn(taskQuery);
|
||||
when(taskQuery.orderByDesc(any(SFunction.class))).thenReturn(taskQuery);
|
||||
when(taskQuery.list()).thenReturn(Collections.singletonList(task));
|
||||
SteadyChecksquareServiceImpl service = new SteadyChecksquareServiceImpl(new SteadyTrendIndicatorCatalog(),
|
||||
mock(SteadyChecksquareInfluxQueryComponent.class), new SteadyChecksquareCalculator(),
|
||||
@@ -200,7 +213,7 @@ class SteadyChecksquareServiceImplTest {
|
||||
LambdaQueryChainWrapper<SteadyChecksquareTaskPO> taskQuery = mock(LambdaQueryChainWrapper.class);
|
||||
when(taskService.lambdaQuery()).thenReturn(taskQuery);
|
||||
when(taskQuery.eq(any(), any())).thenReturn(taskQuery);
|
||||
when(taskQuery.orderByDesc(any())).thenReturn(taskQuery);
|
||||
when(taskQuery.orderByDesc(any(SFunction.class))).thenReturn(taskQuery);
|
||||
when(taskQuery.list()).thenReturn(Collections.emptyList());
|
||||
SteadyChecksquareServiceImpl service = new SteadyChecksquareServiceImpl(new SteadyTrendIndicatorCatalog(),
|
||||
influxQueryComponent, new SteadyChecksquareCalculator(),
|
||||
@@ -660,7 +673,7 @@ class SteadyChecksquareServiceImplTest {
|
||||
SteadyChecksquareItemVO item = new SteadyChecksquareItemVO();
|
||||
item.setItemKey("line-001|V_RMS");
|
||||
item.setIndicatorCode("V_RMS");
|
||||
item.setIndicatorName("鐩哥數鍘嬫湁鏁堝€?);
|
||||
item.setIndicatorName("鐩哥數鍘嬫湁鏁堝€?");
|
||||
item.setIntervalMinutes(1);
|
||||
item.setHasData(true);
|
||||
item.setExpectedPointCount(2);
|
||||
|
||||
@@ -3,8 +3,28 @@
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.njcn.gather.device.types.mapper.CsDevTypeMapper">
|
||||
|
||||
<resultMap id="DeviceTypeVOResultMap"
|
||||
type="com.njcn.gather.device.types.pojo.vo.DeviceTypeVO">
|
||||
<id column="id" property="id"/>
|
||||
<result column="name" property="name"/>
|
||||
<result column="icdId" property="icdId"/>
|
||||
<result column="icdName" property="icdName"/>
|
||||
<result column="icdPath" property="icdPath"/>
|
||||
<result column="icdResult" property="icdResult"/>
|
||||
<result column="icdMsg" property="icdMsg"
|
||||
typeHandler="com.njcn.gather.device.types.typehandler.JsonNodeTypeHandler"/>
|
||||
<result column="power" property="power"/>
|
||||
<result column="devVolt" property="devVolt"/>
|
||||
<result column="devCurr" property="devCurr"/>
|
||||
<result column="devChns" property="devChns"/>
|
||||
<result column="waveCmd" property="waveCmd"/>
|
||||
<result column="reportName" property="reportName"/>
|
||||
<result column="canCheckIcd" property="canCheckIcd"/>
|
||||
<result column="canCheckPqdif" property="canCheckPqdif"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectDeviceTypeCheckList"
|
||||
resultType="com.njcn.gather.device.types.pojo.vo.DeviceTypeVO">
|
||||
resultMap="DeviceTypeVOResultMap">
|
||||
SELECT
|
||||
d.id AS id,
|
||||
d.name AS name,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.njcn.gather.device.types.pojo.vo;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
@@ -29,8 +30,8 @@ public class DeviceTypeVO {
|
||||
@ApiModelProperty("ICD校验结论,0-否,1-是")
|
||||
private Integer icdResult;
|
||||
|
||||
@ApiModelProperty("ICD校验结论描述")
|
||||
private String icdMsg;
|
||||
@ApiModelProperty("ICD校验结论详情JSON")
|
||||
private JsonNode icdMsg;
|
||||
|
||||
@ApiModelProperty("功率字典code,不带单位,单位由前端展示")
|
||||
private String power;
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.njcn.gather.device.types.typehandler;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.ibatis.type.BaseTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* 将 ICD 校验详情 JSON 映射为结构化对象。
|
||||
*/
|
||||
public class JsonNodeTypeHandler extends BaseTypeHandler<JsonNode> {
|
||||
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
|
||||
@Override
|
||||
public void setNonNullParameter(PreparedStatement ps, int i, JsonNode parameter, JdbcType jdbcType)
|
||||
throws SQLException {
|
||||
ps.setString(i, parameter.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonNode getNullableResult(ResultSet rs, String columnName) throws SQLException {
|
||||
return parse(rs.getString(columnName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonNode getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||
return parse(rs.getString(columnIndex));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonNode getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||
return parse(cs.getString(columnIndex));
|
||||
}
|
||||
|
||||
private JsonNode parse(String value) throws SQLException {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return OBJECT_MAPPER.readTree(value);
|
||||
} catch (Exception ex) {
|
||||
throw new SQLException("解析JSON字段失败", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import com.njcn.gather.icd.mapping.pojo.param.IcdConsistencyCheckRequest;
|
||||
import com.njcn.gather.icd.mapping.pojo.vo.IcdConsistencyCheckResponse;
|
||||
import com.njcn.gather.icd.mapping.pojo.vo.IcdConsistencyIssue;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -26,6 +27,7 @@ import java.util.Set;
|
||||
/**
|
||||
* ICD 映射 JSON 一致性校验服务。
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class IcdConsistencyCheckService {
|
||||
@@ -43,6 +45,8 @@ public class IcdConsistencyCheckService {
|
||||
if (request == null) {
|
||||
throw new IllegalArgumentException("ICD 一致性校验请求不能为空");
|
||||
}
|
||||
log.info("ICD一致性校验,标准ICD JSON={}", request.getStandardJson());
|
||||
log.info("ICD一致性校验,待校验ICD JSON={}", request.getCheckedJson());
|
||||
MappingDocument checked = parseMapping(request.getCheckedJson(), "待校验 JSON");
|
||||
MappingDocument standard = parseMapping(request.getStandardJson(), "标准 JSON");
|
||||
|
||||
@@ -50,7 +54,6 @@ public class IcdConsistencyCheckService {
|
||||
validateSelfFormat(checked, "待校验映射", issues);
|
||||
boolean corrected = applySelfMappingRules(checked, issues);
|
||||
validateConsistency(checked, standard, issues);
|
||||
corrected = applyMappingCorrections(checked, standard, issues) || corrected;
|
||||
|
||||
IcdConsistencyCheckResponse response = new IcdConsistencyCheckResponse();
|
||||
response.setResult(issues.isEmpty() ? 1 : 0);
|
||||
@@ -171,7 +174,7 @@ public class IcdConsistencyCheckService {
|
||||
for (DoiItem doi : inst.getDoiList()) {
|
||||
if (isEmpty(doi.getSdiList())) {
|
||||
addIssue(issues, "自身格式校验", instPath + ".doiList[" + buildKey(doi.getName(), doi.getDesc()) + "]",
|
||||
"sdiList 不能为空:" + joinDesc(group.getDesc(), inst.getDesc(), doi.getDesc()), null, null, false);
|
||||
"typeList 不能为空:" + joinDesc(group.getDesc(), inst.getDesc(), doi.getDesc()), null, null, false);
|
||||
continue;
|
||||
}
|
||||
for (SdiItem sdi : doi.getSdiList()) {
|
||||
@@ -189,7 +192,7 @@ public class IcdConsistencyCheckService {
|
||||
compareValue(standard.getIed(), checked.getIed(), "基础字段", "IED", issues, false);
|
||||
compareValue(standard.getLd(), checked.getLd(), "基础字段", "LD", issues, false);
|
||||
compareValue(standard.getDataType(), checked.getDataType(), "基础字段", "DataType", issues, false);
|
||||
compareValue(standard.getUnit(), checked.getUnit(), "基础字段", "unit", issues, true);
|
||||
compareValue(standard.getUnit(), checked.getUnit(), "基础字段", "unit", issues, false);
|
||||
validateReportMapConsistency(checked, standard, issues);
|
||||
validateDataSetConsistency(checked, standard, issues);
|
||||
}
|
||||
@@ -222,7 +225,7 @@ public class IcdConsistencyCheckService {
|
||||
}
|
||||
for (ReportMapItem item : checked.getReportMap()) {
|
||||
if ("统计数据".equals(trimToEmpty(item.getDesc()))) {
|
||||
int adjustedCount = Math.max(0, item.getReportCount() - 1);
|
||||
int adjustedCount = item.getReportCount() - 1;
|
||||
if (item.getReportCount() != adjustedCount) {
|
||||
addIssue(issues, "映射规则", "ReportMap[" + buildReportKey(item) + "].reportCount",
|
||||
"存在 RtFre 实时数据报告,统计数据 reportCount 已按规则减 1",
|
||||
@@ -252,12 +255,12 @@ public class IcdConsistencyCheckService {
|
||||
addIssue(issues, "一致性校验", "ReportMap[" + key + "]", "标准映射中的 ReportMap 对象在待校验映射中不存在", key, null, false);
|
||||
continue;
|
||||
}
|
||||
compareValue(String.valueOf(standardItem.getReportCount()), String.valueOf(checkedItem.getReportCount()), "ReportMap", "ReportMap[" + key + "].reportCount", issues, true);
|
||||
compareValue(standardItem.getBuffered(), checkedItem.getBuffered(), "ReportMap", "ReportMap[" + key + "].buffered", issues, true);
|
||||
compareValue(standardItem.getInst(), checkedItem.getInst(), "ReportMap", "ReportMap[" + key + "].inst", issues, true);
|
||||
compareValue(standardItem.getFlickerFlag(), checkedItem.getFlickerFlag(), "ReportMap", "ReportMap[" + key + "].FlickerFlag", issues, true);
|
||||
compareValue(standardItem.getSelect(), checkedItem.getSelect(), "ReportMap", "ReportMap[" + key + "].Select", issues, true);
|
||||
compareValue(standardItem.getTrgOps(), checkedItem.getTrgOps(), "ReportMap", "ReportMap[" + key + "].TrgOps", issues, true);
|
||||
compareValue(String.valueOf(standardItem.getReportCount()), String.valueOf(checkedItem.getReportCount()), "ReportMap", "ReportMap[" + key + "].reportCount", issues, false);
|
||||
compareValue(standardItem.getBuffered(), checkedItem.getBuffered(), "ReportMap", "ReportMap[" + key + "].buffered", issues, false);
|
||||
compareValue(standardItem.getInst(), checkedItem.getInst(), "ReportMap", "ReportMap[" + key + "].inst", issues, false);
|
||||
compareValue(standardItem.getFlickerFlag(), checkedItem.getFlickerFlag(), "ReportMap", "ReportMap[" + key + "].FlickerFlag", issues, false);
|
||||
compareValue(standardItem.getSelect(), checkedItem.getSelect(), "ReportMap", "ReportMap[" + key + "].Select", issues, false);
|
||||
compareValue(standardItem.getTrgOps(), checkedItem.getTrgOps(), "ReportMap", "ReportMap[" + key + "].TrgOps", issues, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,9 +315,8 @@ public class IcdConsistencyCheckService {
|
||||
}
|
||||
|
||||
private void compareDoiFields(DoiItem checked, DoiItem standard, String path, List<IcdConsistencyIssue> issues) {
|
||||
boolean canCorrectRange = canCorrectDoiRange(checked, standard) && standard.getEnd() <= checked.getIcdcout();
|
||||
compareValue(String.valueOf(standard.getStart()), String.valueOf(checked.getStart()), "doiList", path + ".start", issues, canCorrectRange);
|
||||
compareValue(String.valueOf(standard.getEnd()), String.valueOf(checked.getEnd()), "doiList", path + ".end", issues, canCorrectRange);
|
||||
compareValue(String.valueOf(standard.getStart()), String.valueOf(checked.getStart()), "doiList", path + ".start", issues, false);
|
||||
compareValue(String.valueOf(standard.getEnd()), String.valueOf(checked.getEnd()), "doiList", path + ".end", issues, false);
|
||||
compareValue(standard.getUnit(), checked.getUnit(), "doiList", path + ".unit", issues, false);
|
||||
compareValue(String.valueOf(standard.getCoefficient()), String.valueOf(checked.getCoefficient()), "doiList", path + ".coefficient", issues, false);
|
||||
compareValue(String.valueOf(standard.getBaseflag()), String.valueOf(checked.getBaseflag()), "doiList", path + ".baseflag", issues, false);
|
||||
@@ -322,101 +324,6 @@ public class IcdConsistencyCheckService {
|
||||
compareValue(String.valueOf(standard.getIcdcout()), String.valueOf(checked.getIcdcout()), "doiList", path + ".icdcout", issues, false);
|
||||
}
|
||||
|
||||
private boolean applyMappingCorrections(MappingDocument checked, MappingDocument standard, List<IcdConsistencyIssue> issues) {
|
||||
boolean corrected = false;
|
||||
if (!equalsValue(checked.getUnit(), standard.getUnit())) {
|
||||
checked.setUnit(standard.getUnit());
|
||||
corrected = true;
|
||||
}
|
||||
corrected = correctReportMap(checked, standard) || corrected;
|
||||
corrected = correctDoiRanges(checked, standard, issues) || corrected;
|
||||
return corrected;
|
||||
}
|
||||
|
||||
private boolean correctReportMap(MappingDocument checked, MappingDocument standard) {
|
||||
boolean corrected = false;
|
||||
Map<String, ReportMapItem> checkedMap = new HashMap<String, ReportMapItem>();
|
||||
if (checked.getReportMap() != null) {
|
||||
for (ReportMapItem item : checked.getReportMap()) {
|
||||
checkedMap.put(buildReportKey(item), item);
|
||||
}
|
||||
}
|
||||
if (standard.getReportMap() == null) {
|
||||
return false;
|
||||
}
|
||||
for (ReportMapItem standardItem : standard.getReportMap()) {
|
||||
ReportMapItem checkedItem = checkedMap.get(buildReportKey(standardItem));
|
||||
if (checkedItem != null && !reportOtherFieldsEqual(checkedItem, standardItem)) {
|
||||
checkedItem.setReportCount(standardItem.getReportCount());
|
||||
checkedItem.setBuffered(standardItem.getBuffered());
|
||||
checkedItem.setInst(standardItem.getInst());
|
||||
checkedItem.setFlickerFlag(standardItem.getFlickerFlag());
|
||||
checkedItem.setSelect(standardItem.getSelect());
|
||||
checkedItem.setTrgOps(standardItem.getTrgOps());
|
||||
corrected = true;
|
||||
}
|
||||
}
|
||||
return corrected;
|
||||
}
|
||||
|
||||
private boolean correctDoiRanges(MappingDocument checked, MappingDocument standard, List<IcdConsistencyIssue> issues) {
|
||||
boolean corrected = false;
|
||||
Map<String, DataSetGroupItem> checkedGroups = indexGroups(checked);
|
||||
if (standard.getDataSetList() == null) {
|
||||
return false;
|
||||
}
|
||||
for (DataSetGroupItem standardGroup : standard.getDataSetList()) {
|
||||
DataSetGroupItem checkedGroup = checkedGroups.get(buildKey(standardGroup.getLnClass(), standardGroup.getDesc()));
|
||||
if (checkedGroup == null) {
|
||||
continue;
|
||||
}
|
||||
corrected = correctGroupDoiRanges(checkedGroup, standardGroup, issues) || corrected;
|
||||
}
|
||||
return corrected;
|
||||
}
|
||||
|
||||
private boolean correctGroupDoiRanges(DataSetGroupItem checkedGroup, DataSetGroupItem standardGroup, List<IcdConsistencyIssue> issues) {
|
||||
boolean corrected = false;
|
||||
Map<String, InstItem> checkedInstMap = indexInst(checkedGroup);
|
||||
if (standardGroup.getInstList() == null) {
|
||||
return false;
|
||||
}
|
||||
for (InstItem standardInst : standardGroup.getInstList()) {
|
||||
InstItem checkedInst = checkedInstMap.get(buildKey(standardInst.getInst(), standardInst.getDesc()));
|
||||
if (checkedInst == null) {
|
||||
continue;
|
||||
}
|
||||
corrected = correctInstDoiRanges(checkedGroup, checkedInst, standardInst, issues) || corrected;
|
||||
}
|
||||
return corrected;
|
||||
}
|
||||
|
||||
private boolean correctInstDoiRanges(DataSetGroupItem checkedGroup, InstItem checkedInst, InstItem standardInst, List<IcdConsistencyIssue> issues) {
|
||||
boolean corrected = false;
|
||||
Map<String, DoiItem> checkedDoiMap = indexDoi(checkedInst);
|
||||
if (standardInst.getDoiList() == null) {
|
||||
return false;
|
||||
}
|
||||
for (DoiItem standardDoi : standardInst.getDoiList()) {
|
||||
DoiItem checkedDoi = checkedDoiMap.get(buildKey(standardDoi.getName(), standardDoi.getDesc()));
|
||||
if (checkedDoi == null || !canCorrectDoiRange(checkedDoi, standardDoi)) {
|
||||
continue;
|
||||
}
|
||||
String path = buildInstPath(checkedGroup, checkedInst) + ".doiList[" + buildKey(checkedDoi.getName(), checkedDoi.getDesc()) + "]";
|
||||
if (standardDoi.getEnd() > checkedDoi.getIcdcout()) {
|
||||
addIssue(issues, "映射修改", path, "标准 end 大于待校验 icdcout,不能自动修正 start/end",
|
||||
String.valueOf(standardDoi.getEnd()), String.valueOf(checkedDoi.getIcdcout()), false);
|
||||
continue;
|
||||
}
|
||||
if (checkedDoi.getStart() != standardDoi.getStart() || checkedDoi.getEnd() != standardDoi.getEnd()) {
|
||||
checkedDoi.setStart(standardDoi.getStart());
|
||||
checkedDoi.setEnd(standardDoi.getEnd());
|
||||
corrected = true;
|
||||
}
|
||||
}
|
||||
return corrected;
|
||||
}
|
||||
|
||||
private void compareValue(String standardValue, String checkedValue, String scope, String path,
|
||||
List<IcdConsistencyIssue> issues, boolean corrected) {
|
||||
if (!equalsValue(standardValue, checkedValue)) {
|
||||
@@ -489,20 +396,6 @@ public class IcdConsistencyCheckService {
|
||||
return String.join("+", parts);
|
||||
}
|
||||
|
||||
private boolean reportOtherFieldsEqual(ReportMapItem checked, ReportMapItem standard) {
|
||||
return checked.getReportCount() == standard.getReportCount()
|
||||
&& equalsValue(checked.getBuffered(), standard.getBuffered())
|
||||
&& equalsValue(checked.getInst(), standard.getInst())
|
||||
&& equalsValue(checked.getFlickerFlag(), standard.getFlickerFlag())
|
||||
&& equalsValue(checked.getSelect(), standard.getSelect())
|
||||
&& equalsValue(checked.getTrgOps(), standard.getTrgOps());
|
||||
}
|
||||
|
||||
private boolean canCorrectDoiRange(DoiItem checked, DoiItem standard) {
|
||||
return checked.getBaseflag() == standard.getBaseflag()
|
||||
&& (checked.getBaseflag() == 1 || checked.getBaseflag() == 2);
|
||||
}
|
||||
|
||||
private boolean equalsValue(String left, String right) {
|
||||
return trimToEmpty(left).equals(trimToEmpty(right));
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ public class CsIcdPathController extends BaseController {
|
||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
|
||||
@ApiOperation("保存ICD唯一性校验结果")
|
||||
@ApiImplicitParam(name = "id", value = "ICD记录ID", required = true)
|
||||
@PostMapping("/{id}/icd-check-result")
|
||||
@PostMapping(value = "/{id}/icd-check-result", consumes = {"application/json"})
|
||||
public HttpResult<Boolean> saveIcdCheckResult(@PathVariable("id") String id,
|
||||
@RequestBody IcdCheckResultSaveParam param) {
|
||||
String methodDescribe = getMethodDescribe("saveIcdCheckResult");
|
||||
@@ -127,6 +127,20 @@ public class CsIcdPathController extends BaseController {
|
||||
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
|
||||
}
|
||||
|
||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
|
||||
@ApiOperation("上传并保存ICD唯一性校验结果")
|
||||
@ApiImplicitParam(name = "id", value = "ICD记录ID", required = true)
|
||||
@PostMapping(value = "/{id}/icd-check-result", consumes = {"multipart/form-data"})
|
||||
public HttpResult<Boolean> saveIcdCheckResultWithFile(@PathVariable("id") String id,
|
||||
@RequestPart("icdFile") MultipartFile icdFile,
|
||||
@RequestPart("request") IcdCheckResultSaveParam param) {
|
||||
String methodDescribe = getMethodDescribe("saveIcdCheckResultWithFile");
|
||||
LogUtil.njcnDebug(log, "{},开始上传并保存ICD校验结果,icdId={},fileName={}", methodDescribe, id, resolveFileName(icdFile));
|
||||
fillIcdFile(param, icdFile);
|
||||
boolean result = csIcdPathService.saveIcdCheckResult(id, param);
|
||||
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
|
||||
}
|
||||
|
||||
private void fillIcdFile(CsIcdPathParam param, MultipartFile icdFile) {
|
||||
if (icdFile == null || icdFile.isEmpty()) {
|
||||
throw new IllegalArgumentException("ICD文件不能为空");
|
||||
@@ -141,6 +155,20 @@ public class CsIcdPathController extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
private void fillIcdFile(IcdCheckResultSaveParam param, MultipartFile icdFile) {
|
||||
if (param == null) {
|
||||
throw new IllegalArgumentException("ICD校验结果不能为空");
|
||||
}
|
||||
if (icdFile == null || icdFile.isEmpty()) {
|
||||
throw new IllegalArgumentException("ICD文件不能为空");
|
||||
}
|
||||
try {
|
||||
param.setIcdContent(icdFile.getBytes());
|
||||
} catch (IOException ex) {
|
||||
throw new IllegalArgumentException("读取ICD文件失败:" + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveFileName(MultipartFile icdFile) {
|
||||
if (icdFile == null || icdFile.getOriginalFilename() == null) {
|
||||
return null;
|
||||
|
||||
@@ -3,8 +3,29 @@
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.njcn.gather.icd.mapping.mapper.CsIcdPathMapper">
|
||||
|
||||
<resultMap id="CsIcdPathVOResultMap"
|
||||
type="com.njcn.gather.icd.mapping.pojo.vo.CsIcdPathVO">
|
||||
<id column="id" property="id"/>
|
||||
<result column="name" property="name"/>
|
||||
<result column="path" property="path"/>
|
||||
<result column="angle" property="angle"/>
|
||||
<result column="usePhaseIndex" property="usePhaseIndex"/>
|
||||
<result column="state" property="state"/>
|
||||
<result column="jsonStr" property="jsonStr"/>
|
||||
<result column="xmlStr" property="xmlStr"/>
|
||||
<result column="result" property="result"/>
|
||||
<result column="msg" property="msg"
|
||||
typeHandler="com.njcn.gather.icd.mapping.typehandler.JsonNodeTypeHandler"/>
|
||||
<result column="type" property="type"/>
|
||||
<result column="referenceIcdId" property="referenceIcdId"/>
|
||||
<result column="createBy" property="createBy"/>
|
||||
<result column="createTime" property="createTime"/>
|
||||
<result column="updateBy" property="updateBy"/>
|
||||
<result column="updateTime" property="updateTime"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectIcdPathList"
|
||||
resultType="com.njcn.gather.icd.mapping.pojo.vo.CsIcdPathVO">
|
||||
resultMap="CsIcdPathVOResultMap">
|
||||
SELECT
|
||||
ID AS id,
|
||||
Name AS name,
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.param;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.njcn.gather.icd.mapping.pojo.bo.icd.IcdDocument;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
@@ -20,6 +23,13 @@ public class IcdCheckResultSaveParam {
|
||||
@ApiModelProperty("校验结论:0-否,1-是")
|
||||
private Integer result;
|
||||
|
||||
@ApiModelProperty("校验结论描述")
|
||||
private String msg;
|
||||
@ApiModelProperty("校验结论详情JSON")
|
||||
private JsonNode msg;
|
||||
|
||||
@ApiModelProperty("getICD返回的icdDocument原始解析记录")
|
||||
private IcdDocument icdDocument;
|
||||
|
||||
@ApiModelProperty("ICD文件二进制内容,仅 multipart 保存时由后端填充")
|
||||
@JsonIgnore
|
||||
private byte[] icdContent;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.njcn.gather.icd.mapping.pojo.po;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.njcn.gather.icd.mapping.typehandler.JsonNodeTypeHandler;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
@@ -12,7 +14,7 @@ import java.time.LocalDateTime;
|
||||
* ICD 存储记录。
|
||||
*/
|
||||
@Data
|
||||
@TableName("cs_icd_path")
|
||||
@TableName(value = "cs_icd_path", autoResultMap = true)
|
||||
public class CsIcdPathPO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
@@ -26,7 +28,7 @@ public class CsIcdPathPO implements Serializable {
|
||||
@TableField("Path")
|
||||
private String path;
|
||||
|
||||
@TableField("Icd_Content")
|
||||
@TableField("Icd")
|
||||
private byte[] icdContent;
|
||||
|
||||
@TableField("Angle")
|
||||
@@ -59,8 +61,8 @@ public class CsIcdPathPO implements Serializable {
|
||||
@TableField("Result")
|
||||
private Integer result;
|
||||
|
||||
@TableField("Msg")
|
||||
private String msg;
|
||||
@TableField(value = "Msg", typeHandler = JsonNodeTypeHandler.class)
|
||||
private JsonNode msg;
|
||||
|
||||
@TableField("Type")
|
||||
private Integer type;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.vo;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
@@ -40,8 +41,8 @@ public class CsIcdPathVO {
|
||||
@ApiModelProperty("校验结论,0-否,1-是")
|
||||
private Integer result;
|
||||
|
||||
@ApiModelProperty("校验结论描述")
|
||||
private String msg;
|
||||
@ApiModelProperty("校验结论详情JSON")
|
||||
private JsonNode msg;
|
||||
|
||||
@ApiModelProperty("ICD类型,1-标准ICD")
|
||||
private Integer type;
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.njcn.gather.icd.mapping.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.njcn.gather.icd.mapping.mapper.CsIcdPathMapper;
|
||||
import com.njcn.gather.icd.mapping.pojo.param.CsIcdPathParam;
|
||||
import com.njcn.gather.icd.mapping.pojo.param.IcdCheckResultSaveParam;
|
||||
@@ -32,6 +34,8 @@ public class CsIcdPathServiceImpl implements CsIcdPathService {
|
||||
|
||||
private final CsIcdPathMapper csIcdPathMapper;
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Override
|
||||
public List<CsIcdPathVO> listIcdPaths(CsIcdPathParam.ListParam param) {
|
||||
CsIcdPathParam.ListParam checkedParam = param == null ? new CsIcdPathParam.ListParam() : param;
|
||||
@@ -116,13 +120,26 @@ public class CsIcdPathServiceImpl implements CsIcdPathService {
|
||||
icdPath.setJsonStr(trimToNull(param.getMappingJson()));
|
||||
icdPath.setXmlStr(trimToNull(param.getXml()));
|
||||
icdPath.setResult(normalizeResult(param.getResult()));
|
||||
icdPath.setMsg(trimToNull(param.getMsg()));
|
||||
icdPath.setMsg(param.getMsg());
|
||||
icdPath.setReferenceIcdId(referenceIcd.getId());
|
||||
if (param.getIcdDocument() != null) {
|
||||
icdPath.setIcdContent(serializeIcdDocument(param));
|
||||
} else if (param.getIcdContent() != null && param.getIcdContent().length > 0) {
|
||||
icdPath.setIcdContent(param.getIcdContent());
|
||||
}
|
||||
icdPath.setUpdateBy(currentUserId());
|
||||
icdPath.setUpdateTime(LocalDateTime.now());
|
||||
return csIcdPathMapper.updateById(icdPath) > 0;
|
||||
}
|
||||
|
||||
private byte[] serializeIcdDocument(IcdCheckResultSaveParam param) {
|
||||
try {
|
||||
return objectMapper.writeValueAsBytes(param.getIcdDocument());
|
||||
} catch (JsonProcessingException ex) {
|
||||
throw new IllegalArgumentException("ICD解析记录序列化失败:" + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private CsIcdPathPO buildIcdPath(CsIcdPathParam param) {
|
||||
CsIcdPathPO icdPath = new CsIcdPathPO();
|
||||
icdPath.setName(requireText(param.getName(), "ICD名称不能为空"));
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.njcn.gather.icd.mapping.typehandler;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.ibatis.type.BaseTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* 将数据库 JSON 字段映射为 Jackson JsonNode,便于接口直接返回结构化失败原因。
|
||||
*/
|
||||
public class JsonNodeTypeHandler extends BaseTypeHandler<JsonNode> {
|
||||
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
|
||||
@Override
|
||||
public void setNonNullParameter(PreparedStatement ps, int i, JsonNode parameter, JdbcType jdbcType)
|
||||
throws SQLException {
|
||||
ps.setString(i, parameter.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonNode getNullableResult(ResultSet rs, String columnName) throws SQLException {
|
||||
return parse(rs.getString(columnName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonNode getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||
return parse(rs.getString(columnIndex));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonNode getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||
return parse(cs.getString(columnIndex));
|
||||
}
|
||||
|
||||
private JsonNode parse(String value) throws SQLException {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return OBJECT_MAPPER.readTree(value);
|
||||
} catch (Exception ex) {
|
||||
throw new SQLException("解析JSON字段失败", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ class IcdConsistencyCheckServiceTest {
|
||||
Path tempDir;
|
||||
|
||||
@Test
|
||||
void checkShouldReturnMismatchIssuesAndCorrectedJsonWithoutSavedPath() throws Exception {
|
||||
void checkShouldReturnMismatchIssuesWithoutAutoCorrectingConsistencyDiffs() throws Exception {
|
||||
IcdConsistencyCheckRequest request = new IcdConsistencyCheckRequest();
|
||||
request.setStandardJson(buildStandardJson());
|
||||
request.setCheckedJson(buildCheckedJson());
|
||||
@@ -31,13 +31,38 @@ class IcdConsistencyCheckServiceTest {
|
||||
Assertions.assertEquals("不符合", response.getMessage());
|
||||
Assertions.assertFalse(response.getIssues().isEmpty());
|
||||
Assertions.assertTrue(response.getIssuesJson().contains("ReportMap"));
|
||||
Assertions.assertTrue(response.getCorrectedJson().contains("\"unit\" : \"s\""));
|
||||
Assertions.assertTrue(response.getCorrectedJson().contains("\"reportCount\" : 2"));
|
||||
Assertions.assertTrue(response.getCorrectedJson().contains("\"start\" : 1"));
|
||||
Assertions.assertTrue(response.getCorrectedJson().contains("\"end\" : 4"));
|
||||
Assertions.assertNull(response.getCorrectedJson());
|
||||
Assertions.assertTrue(Files.list(tempDir).findAny().isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkShouldOnlyReturnCorrectedJsonForRtFreSelfMappingRule() {
|
||||
IcdConsistencyCheckRequest request = new IcdConsistencyCheckRequest();
|
||||
request.setStandardJson(buildRtFreStandardJson());
|
||||
request.setCheckedJson(buildRtFreCheckedJson());
|
||||
|
||||
IcdConsistencyCheckResponse response = service.check(request);
|
||||
|
||||
Assertions.assertEquals(0, response.getResult());
|
||||
Assertions.assertTrue(response.getCorrectedJson().contains("\"rptID\" : \"demoRtFre\""));
|
||||
Assertions.assertTrue(response.getCorrectedJson().contains("\"FlickerFlag\" : \"1\""));
|
||||
Assertions.assertTrue(response.getCorrectedJson().contains("\"reportCount\" : 0"));
|
||||
Assertions.assertTrue(response.getCorrectedJson().contains("\"reportCount\" : 1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkShouldReportEmptySdiListAsTypeListProblem() {
|
||||
IcdConsistencyCheckRequest request = new IcdConsistencyCheckRequest();
|
||||
request.setStandardJson(buildStandardJson());
|
||||
request.setCheckedJson(buildEmptySdiListJson());
|
||||
|
||||
IcdConsistencyCheckResponse response = service.check(request);
|
||||
|
||||
Assertions.assertEquals(0, response.getResult());
|
||||
Assertions.assertTrue(response.getIssuesJson().contains("typeList 不能为空:统计数据 / A相 / 频率"));
|
||||
Assertions.assertFalse(response.getIssuesJson().contains("sdiList 不能为空"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkShouldReturnPassWhenCheckedJsonMatchesStandardJson() {
|
||||
IcdConsistencyCheckRequest request = new IcdConsistencyCheckRequest();
|
||||
@@ -94,6 +119,69 @@ class IcdConsistencyCheckServiceTest {
|
||||
"}";
|
||||
}
|
||||
|
||||
private String buildRtFreStandardJson() {
|
||||
return "{\n" +
|
||||
" \"IED\":\"IED1\",\n" +
|
||||
" \"LD\":\"LD0\",\n" +
|
||||
" \"DataType\":\"1\",\n" +
|
||||
" \"unit\":\"s\",\n" +
|
||||
" \"ReportMap\":[\n" +
|
||||
" {\"desc\":\"统计数据\",\"reportCount\":1,\"rptID\":\"rpt-stat\",\"name\":\"brcbStat\",\"buffered\":\"BR\",\"inst\":\"01\",\"FlickerFlag\":\"0\",\"Select\":\"all\",\"TrgOps\":\"dchg\"},\n" +
|
||||
" {\"desc\":\"波动闪变\",\"reportCount\":1,\"rptID\":\"rpt-flk\",\"name\":\"brcbFlk\",\"buffered\":\"BR\",\"inst\":\"02\",\"FlickerFlag\":\"0\",\"Select\":\"all\",\"TrgOps\":\"dchg\"},\n" +
|
||||
" {\"desc\":\"实时数据\",\"reportCount\":0,\"rptID\":\"demoRtFre\",\"name\":\"brcbRt\",\"buffered\":\"RP\",\"inst\":\"03\",\"FlickerFlag\":\"1\",\"Select\":\"all\",\"TrgOps\":\"dchg\"},\n" +
|
||||
" {\"desc\":\"暂态事件\",\"reportCount\":1,\"rptID\":\"rpt-tran\",\"name\":\"brcbTran\",\"buffered\":\"BR\",\"inst\":\"04\",\"FlickerFlag\":\"0\",\"Select\":\"all\",\"TrgOps\":\"dchg\"}\n" +
|
||||
" ],\n" +
|
||||
" \"DataSetList\":[\n" +
|
||||
buildDataSet("MMXU", "统计数据", "1", "A相", "Hz", "频率", 1, 4, "Hz") + ",\n" +
|
||||
buildDataSet("MSQI", "实时数据", "1", "A相", "A", "电流", 1, 2, "A") + ",\n" +
|
||||
buildDataSet("MHAI", "谐波数据", "1", "A相", "Har", "谐波", 1, 2, "%") + ",\n" +
|
||||
buildDataSet("MFLK", "波动闪变", "1", "A相", "Flk", "闪变", 1, 2, "pu") + "\n" +
|
||||
" ]\n" +
|
||||
"}";
|
||||
}
|
||||
|
||||
private String buildRtFreCheckedJson() {
|
||||
return "{\n" +
|
||||
" \"IED\":\"IED1\",\n" +
|
||||
" \"LD\":\"LD0\",\n" +
|
||||
" \"DataType\":\"1\",\n" +
|
||||
" \"unit\":\"s\",\n" +
|
||||
" \"ReportMap\":[\n" +
|
||||
" {\"desc\":\"统计数据\",\"reportCount\":2,\"rptID\":\"rpt-stat\",\"name\":\"brcbStat\",\"buffered\":\"BR\",\"inst\":\"01\",\"FlickerFlag\":\"0\",\"Select\":\"all\",\"TrgOps\":\"dchg\"},\n" +
|
||||
" {\"desc\":\"波动闪变\",\"reportCount\":1,\"rptID\":\"rpt-flk\",\"name\":\"brcbFlk\",\"buffered\":\"BR\",\"inst\":\"02\",\"FlickerFlag\":\"0\",\"Select\":\"all\",\"TrgOps\":\"dchg\"},\n" +
|
||||
" {\"desc\":\"实时数据\",\"reportCount\":1,\"rptID\":\"demoRtFre\",\"name\":\"brcbRt\",\"buffered\":\"RP\",\"inst\":\"03\",\"FlickerFlag\":\"0\",\"Select\":\"all\",\"TrgOps\":\"dchg\"},\n" +
|
||||
" {\"desc\":\"暂态事件\",\"reportCount\":1,\"rptID\":\"rpt-tran\",\"name\":\"brcbTran\",\"buffered\":\"BR\",\"inst\":\"04\",\"FlickerFlag\":\"0\",\"Select\":\"all\",\"TrgOps\":\"dchg\"}\n" +
|
||||
" ],\n" +
|
||||
" \"DataSetList\":[\n" +
|
||||
buildDataSet("MMXU", "统计数据", "1", "A相", "Hz", "频率", 1, 4, "Hz") + ",\n" +
|
||||
buildDataSet("MSQI", "实时数据", "1", "A相", "A", "电流", 1, 2, "A") + ",\n" +
|
||||
buildDataSet("MHAI", "谐波数据", "1", "A相", "Har", "谐波", 1, 2, "%") + ",\n" +
|
||||
buildDataSet("MFLK", "波动闪变", "1", "A相", "Flk", "闪变", 1, 2, "pu") + "\n" +
|
||||
" ]\n" +
|
||||
"}";
|
||||
}
|
||||
|
||||
private String buildEmptySdiListJson() {
|
||||
return "{\n" +
|
||||
" \"IED\":\"IED1\",\n" +
|
||||
" \"LD\":\"LD0\",\n" +
|
||||
" \"DataType\":\"1\",\n" +
|
||||
" \"unit\":\"s\",\n" +
|
||||
" \"ReportMap\":[\n" +
|
||||
" {\"desc\":\"统计数据\",\"reportCount\":2,\"rptID\":\"rpt-stat\",\"name\":\"brcbStat\",\"buffered\":\"BR\",\"inst\":\"01\",\"FlickerFlag\":\"0\",\"Select\":\"all\",\"TrgOps\":\"dchg\"},\n" +
|
||||
" {\"desc\":\"波动闪变\",\"reportCount\":1,\"rptID\":\"rpt-flk\",\"name\":\"brcbFlk\",\"buffered\":\"BR\",\"inst\":\"02\",\"FlickerFlag\":\"0\",\"Select\":\"all\",\"TrgOps\":\"dchg\"},\n" +
|
||||
" {\"desc\":\"实时数据\",\"reportCount\":1,\"rptID\":\"rpt-rt\",\"name\":\"brcbRt\",\"buffered\":\"RP\",\"inst\":\"03\",\"FlickerFlag\":\"0\",\"Select\":\"all\",\"TrgOps\":\"dchg\"},\n" +
|
||||
" {\"desc\":\"暂态事件\",\"reportCount\":1,\"rptID\":\"rpt-tran\",\"name\":\"brcbTran\",\"buffered\":\"BR\",\"inst\":\"04\",\"FlickerFlag\":\"0\",\"Select\":\"all\",\"TrgOps\":\"dchg\"}\n" +
|
||||
" ],\n" +
|
||||
" \"DataSetList\":[\n" +
|
||||
buildDataSetWithoutSdiList("MMXU", "统计数据", "1", "A相", "Hz", "频率") + ",\n" +
|
||||
buildDataSet("MSQI", "实时数据", "1", "A相", "A", "电流", 1, 2, "A") + ",\n" +
|
||||
buildDataSet("MHAI", "谐波数据", "1", "A相", "Har", "谐波", 1, 2, "%") + ",\n" +
|
||||
buildDataSet("MFLK", "波动闪变", "1", "A相", "Flk", "闪变", 1, 2, "pu") + "\n" +
|
||||
" ]\n" +
|
||||
"}";
|
||||
}
|
||||
|
||||
private String buildDataSet(String lnClass, String groupDesc, String inst, String instDesc,
|
||||
String doiName, String doiDesc, int start, int end, String unit) {
|
||||
return " {\"desc\":\"" + groupDesc + "\",\"lnClass\":\"" + lnClass + "\",\"instList\":[{\"inst\":\"" + inst +
|
||||
@@ -101,4 +189,11 @@ class IcdConsistencyCheckServiceTest {
|
||||
"\",\"start\":" + start + ",\"end\":" + end + ",\"unit\":\"" + unit +
|
||||
"\",\"coefficient\":1.0,\"baseflag\":1,\"basecount\":1,\"icdcout\":10,\"sdiList\":[{\"name\":\"mag\",\"desc\":\"幅值\",\"typeList\":[{\"name\":\"f\",\"desc\":\"浮点\"}]}]}]}]}";
|
||||
}
|
||||
|
||||
private String buildDataSetWithoutSdiList(String lnClass, String groupDesc, String inst, String instDesc,
|
||||
String doiName, String doiDesc) {
|
||||
return " {\"desc\":\"" + groupDesc + "\",\"lnClass\":\"" + lnClass + "\",\"instList\":[{\"inst\":\"" + inst +
|
||||
"\",\"desc\":\"" + instDesc + "\",\"doiList\":[{\"name\":\"" + doiName + "\",\"desc\":\"" + doiDesc +
|
||||
"\",\"start\":1,\"end\":4,\"unit\":\"Hz\",\"coefficient\":1.0,\"baseflag\":1,\"basecount\":1,\"icdcout\":10,\"sdiList\":[]}]}]}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package com.njcn.gather.icd.mapping.service.impl;
|
||||
|
||||
import com.njcn.gather.icd.mapping.mapper.CsIcdPathMapper;
|
||||
import com.njcn.gather.icd.mapping.pojo.bo.icd.IcdDocument;
|
||||
import com.njcn.gather.icd.mapping.pojo.param.CsIcdPathParam;
|
||||
import com.njcn.gather.icd.mapping.pojo.param.IcdCheckResultSaveParam;
|
||||
import com.njcn.gather.icd.mapping.pojo.po.CsIcdPathPO;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
@@ -19,9 +22,21 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
class CsIcdPathServiceImplTest {
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
private final CsIcdPathMapper csIcdPathMapper = mock(CsIcdPathMapper.class);
|
||||
private final CsIcdPathServiceImpl service = new CsIcdPathServiceImpl(csIcdPathMapper);
|
||||
|
||||
@Test
|
||||
void checkResultParamShouldIgnoreIcdContentFromJson() throws Exception {
|
||||
String requestJson = "{\"mappingJson\":\"{}\",\"result\":1,\"icdContent\":\"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\"}";
|
||||
|
||||
IcdCheckResultSaveParam param = objectMapper.readValue(requestJson, IcdCheckResultSaveParam.class);
|
||||
|
||||
Assertions.assertEquals("{}", param.getMappingJson());
|
||||
Assertions.assertEquals(1, param.getResult());
|
||||
Assertions.assertNull(param.getIcdContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void listIcdPathsShouldTrimKeywordBeforeQuery() {
|
||||
CsIcdPathParam.ListParam param = new CsIcdPathParam.ListParam();
|
||||
@@ -152,7 +167,8 @@ class CsIcdPathServiceImplTest {
|
||||
param.setMappingJson("{}");
|
||||
param.setXml("<xml/>");
|
||||
param.setResult(1);
|
||||
param.setMsg("通过");
|
||||
JsonNode msg = objectMapper.createObjectNode().put("summary", "通过");
|
||||
param.setMsg(msg);
|
||||
|
||||
boolean result = service.saveIcdCheckResult("icd-001", param);
|
||||
|
||||
@@ -161,6 +177,62 @@ class CsIcdPathServiceImplTest {
|
||||
Assertions.assertTrue(result);
|
||||
Assertions.assertEquals("reference-icd", captor.getValue().getReferenceIcdId());
|
||||
Assertions.assertEquals(1, captor.getValue().getResult());
|
||||
Assertions.assertEquals("通过", captor.getValue().getMsg().get("summary").asText());
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveIcdCheckResultShouldSaveIcdBinaryContentWhenProvided() {
|
||||
CsIcdPathPO referenceIcd = new CsIcdPathPO();
|
||||
referenceIcd.setId("reference-icd");
|
||||
when(csIcdPathMapper.selectList(any())).thenReturn(Collections.singletonList(referenceIcd));
|
||||
|
||||
CsIcdPathPO icdPath = new CsIcdPathPO();
|
||||
icdPath.setId("icd-001");
|
||||
icdPath.setState(1);
|
||||
when(csIcdPathMapper.selectById(eq("icd-001"))).thenReturn(icdPath);
|
||||
when(csIcdPathMapper.updateById(any(CsIcdPathPO.class))).thenReturn(1);
|
||||
|
||||
byte[] fileContent = "<SCL name=\"checked\"></SCL>".getBytes();
|
||||
IcdCheckResultSaveParam param = new IcdCheckResultSaveParam();
|
||||
param.setMappingJson("{}");
|
||||
param.setResult(1);
|
||||
param.setIcdContent(fileContent);
|
||||
|
||||
boolean result = service.saveIcdCheckResult("icd-001", param);
|
||||
|
||||
ArgumentCaptor<CsIcdPathPO> captor = ArgumentCaptor.forClass(CsIcdPathPO.class);
|
||||
verify(csIcdPathMapper).updateById(captor.capture());
|
||||
Assertions.assertTrue(result);
|
||||
Assertions.assertArrayEquals(fileContent, captor.getValue().getIcdContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveIcdCheckResultShouldSaveIcdDocumentJsonContentWhenProvided() throws Exception {
|
||||
CsIcdPathPO referenceIcd = new CsIcdPathPO();
|
||||
referenceIcd.setId("reference-icd");
|
||||
when(csIcdPathMapper.selectList(any())).thenReturn(Collections.singletonList(referenceIcd));
|
||||
|
||||
CsIcdPathPO icdPath = new CsIcdPathPO();
|
||||
icdPath.setId("icd-001");
|
||||
icdPath.setState(1);
|
||||
when(csIcdPathMapper.selectById(eq("icd-001"))).thenReturn(icdPath);
|
||||
when(csIcdPathMapper.updateById(any(CsIcdPathPO.class))).thenReturn(1);
|
||||
|
||||
IcdDocument icdDocument = new IcdDocument();
|
||||
icdDocument.setFileName("checked.icd");
|
||||
icdDocument.setIedName("IED1");
|
||||
icdDocument.setLdInst("LD0");
|
||||
IcdCheckResultSaveParam param = new IcdCheckResultSaveParam();
|
||||
param.setMappingJson("{}");
|
||||
param.setResult(1);
|
||||
param.setIcdDocument(icdDocument);
|
||||
|
||||
boolean result = service.saveIcdCheckResult("icd-001", param);
|
||||
|
||||
ArgumentCaptor<CsIcdPathPO> captor = ArgumentCaptor.forClass(CsIcdPathPO.class);
|
||||
verify(csIcdPathMapper).updateById(captor.capture());
|
||||
Assertions.assertTrue(result);
|
||||
Assertions.assertArrayEquals(objectMapper.writeValueAsBytes(icdDocument), captor.getValue().getIcdContent());
|
||||
}
|
||||
|
||||
private CsIcdPathParam buildParam(String name) {
|
||||
|
||||
Reference in New Issue
Block a user