package jnpf.elnService.impl;
|
|
import jnpf.base.ActionResult;
|
import jnpf.eln.RecordFreezeCheckBatch;
|
import jnpf.eln.RecordFreezeCheckRequest;
|
import jnpf.eln.RecordFreezeCheckResult;
|
import jnpf.eln.RecordFreezeReleaseRequest;
|
import jnpf.elnEntity.field.ElnFieldVersionEntity;
|
import jnpf.elnEntity.formula.ElnTemplateFormulaBindingEntity;
|
import jnpf.elnEntity.runtime.ElnRecordEntity;
|
import jnpf.elnEntity.runtime.ElnRecordFieldValueEntity;
|
import jnpf.elnEntity.runtime.ElnRecordFormulaCalculationResult;
|
import jnpf.elnEntity.runtime.ElnRecordRepeatRowEntity;
|
import jnpf.elnEntity.runtime.ElnRecordRepeatValueEntity;
|
import jnpf.elnEntity.runtime.ElnRecordRevisionEntity;
|
import jnpf.elnEntity.template.ElnTemplateBindingEntity;
|
import jnpf.elnMapper.ElnFieldVersionMapper;
|
import jnpf.elnMapper.ElnRecordFieldValueMapper;
|
import jnpf.elnMapper.ElnRecordMapper;
|
import jnpf.elnMapper.ElnRecordRepeatValueMapper;
|
import jnpf.elnMapper.ElnRecordRevisionMapper;
|
import jnpf.elnMapper.ElnRecordSaveOperationMapper;
|
import jnpf.elnMapper.ElnTemplateBindingMapper;
|
import jnpf.elnMapper.ElnTemplateFormulaBindingMapper;
|
import jnpf.elnService.ElnRecordFormulaCalculationService;
|
import jnpf.elnService.ElnCrossTemplateSnapshotResolver;
|
import jnpf.elnService.ElnRecordSourceSyncOperationCoordinator;
|
import jnpf.elnService.field.ElnTestResultFields;
|
import jnpf.elnService.template.ElnTemplateDocumentEvidence;
|
import jnpf.elnService.template.docx.DocxControlSnapshot;
|
import jnpf.onlyoffice.RecordRevisionFenceApi;
|
import org.junit.Before;
|
import org.junit.Test;
|
|
import java.util.Arrays;
|
import java.util.Collections;
|
import java.util.Date;
|
import java.util.List;
|
import java.math.BigDecimal;
|
|
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertTrue;
|
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.when;
|
|
public class ElnRecordFreezeCheckServiceImplTest {
|
private ElnRecordMapper recordMapper;
|
private ElnRecordRevisionMapper revisionMapper;
|
private ElnRecordFieldValueMapper valueMapper;
|
private ElnRecordRepeatValueMapper repeatValueMapper;
|
private ElnRecordSaveOperationMapper operationMapper;
|
private ElnTemplateBindingMapper bindingMapper;
|
private ElnTemplateFormulaBindingMapper formulaBindingMapper;
|
private ElnFieldVersionMapper versionMapper;
|
private ElnRecordFormulaCalculationService calculation;
|
private ElnTemplateDocumentEvidence evidence;
|
private RecordRevisionFenceApi fence;
|
private ElnCrossTemplateSnapshotResolver crossTemplateSnapshotResolver;
|
private ElnRecordSourceSyncOperationCoordinator sourceSyncOperations;
|
private ElnRecordFreezeCheckServiceImpl service;
|
|
@Before
|
public void setUp() {
|
recordMapper = mock(ElnRecordMapper.class);
|
revisionMapper = mock(ElnRecordRevisionMapper.class);
|
valueMapper = mock(ElnRecordFieldValueMapper.class);
|
repeatValueMapper = mock(ElnRecordRepeatValueMapper.class);
|
operationMapper = mock(ElnRecordSaveOperationMapper.class);
|
bindingMapper = mock(ElnTemplateBindingMapper.class);
|
formulaBindingMapper = mock(ElnTemplateFormulaBindingMapper.class);
|
versionMapper = mock(ElnFieldVersionMapper.class);
|
calculation = mock(ElnRecordFormulaCalculationService.class);
|
evidence = mock(ElnTemplateDocumentEvidence.class);
|
fence = mock(RecordRevisionFenceApi.class);
|
crossTemplateSnapshotResolver = mock(ElnCrossTemplateSnapshotResolver.class);
|
sourceSyncOperations = mock(ElnRecordSourceSyncOperationCoordinator.class);
|
service = new ElnRecordFreezeCheckServiceImpl(recordMapper, revisionMapper, valueMapper,
|
repeatValueMapper,
|
operationMapper, bindingMapper, formulaBindingMapper, versionMapper, calculation, evidence, fence,
|
new ElnRecordFreezeCheckServiceImpl.TenantRoute() {
|
@Override public void switchTo(String tenantId) { }
|
@Override public void clear() { }
|
}, crossTemplateSnapshotResolver, sourceSyncOperations);
|
}
|
|
@Test
|
public void returnsNotApplicableForItemsWithoutElnRecord() {
|
RecordFreezeCheckBatch batch = service.prepare(request("item-1"));
|
assertEquals(RecordFreezeCheckResult.NOT_APPLICABLE, batch.getItems().get(0).getStatus());
|
}
|
|
@Test
|
public void blocksFreezeWhileSourceSynchronizationAwaitsDocumentConfirmation() {
|
arrangeRecord("item-1", "value", "value", 0, "SUCCESS", "PRIMARY", "field-1");
|
when(sourceSyncOperations.hasPendingDocumentConfirmation("tenant-1", "record-1"))
|
.thenReturn(true);
|
|
RecordFreezeCheckResult result = service.prepare(request("item-1")).getItems().get(0);
|
|
assertEquals(RecordFreezeCheckResult.BLOCKED, result.getStatus());
|
assertTrue(result.getDiagnostics().stream().anyMatch(issue ->
|
"SOURCE_SYNC_DOCUMENT_PENDING".equals(issue.getCode())));
|
}
|
|
@Test
|
public void usesRecalculatedValueForDocumentComparisonAndKeepsFenceUntilRelease() {
|
arrangeRecord("item-1", "old", "new", 0, "SUCCESS", "PRIMARY", "field-1");
|
when(calculation.recalculateAll(anyString(), any(), any(), any(), anyString(), anyString())).thenAnswer(invocation -> {
|
ElnRecordFieldValueEntity value = ((List<ElnRecordFieldValueEntity>) invocation.getArgument(3)).get(0);
|
value.setZhiWenben("new");
|
value.setJisuanZhuangtai("SUCCESS");
|
return Collections.singletonList(value);
|
});
|
|
RecordFreezeCheckResult result = service.prepare(request("item-1")).getItems().get(0);
|
|
assertEquals(result.getDiagnostics().toString(), RecordFreezeCheckResult.READY, result.getStatus());
|
assertTrue(result.getReleaseToken().startsWith("freeze:op-1:item-1"));
|
verify(fence).acquireForOperation("tenant-1", "record-1", "record.docx", "annex", "op-1:item-1");
|
RecordFreezeReleaseRequest release = new RecordFreezeReleaseRequest();
|
release.setTenantId("tenant-1");
|
release.setOperationCode("op-1");
|
release.setTestWorkItemIds(Collections.singletonList("item-1"));
|
assertTrue(service.release(release));
|
verify(fence).release("tenant-1", "record-1", "record.docx", "annex", "freeze:op-1:item-1");
|
}
|
|
@Test
|
public void returnsStableTestSubmissionValuesOnlyForReadyRecord() {
|
arrangeRecord("item-1", "expected", "expected", 0, "SUCCESS", "PRIMARY", "field-1");
|
when(calculation.recalculateAll(anyString(), any(), any(), any(), anyString(), anyString()))
|
.thenReturn(Collections.emptyList());
|
|
RecordFreezeCheckResult result = service.prepare(request("item-1")).getItems().get(0);
|
|
assertEquals(RecordFreezeCheckResult.READY, result.getStatus());
|
assertEquals("ELN 检验结果", result.getTestResult());
|
assertEquals("compliant", result.getTestConclusion());
|
}
|
|
@Test
|
public void aggregatesRequiredFormulaDocumentReferenceAndConcurrencyIssues() {
|
arrangeRecord("item-1", "", "x", 1, "ERROR", "WRONG_ROLE", "field-1");
|
ElnTemplateBindingEntity reference = binding("reference-1", "REFERENCE", "eln.ref.field", "field-other");
|
reference.setYinyongShiliId("binding-1");
|
when(bindingMapper.selectList(any())).thenReturn(Arrays.asList(binding("binding-1", "PRIMARY", "eln.field.field", "field-1"), reference));
|
when(operationMapper.selectCount(any())).thenReturn(1L);
|
when(calculation.recalculateAll(anyString(), any(), any(), any(), anyString(), anyString())).thenReturn(Collections.emptyList());
|
|
RecordFreezeCheckResult result = service.prepare(request("item-1")).getItems().get(0);
|
|
assertEquals(RecordFreezeCheckResult.BLOCKED, result.getStatus());
|
assertTrue(hasCategory(result, "REQUIRED"));
|
assertTrue(hasCategory(result, "FORMULA"));
|
assertTrue(hasCategory(result, "DOCUMENT"));
|
assertTrue(hasCategory(result, "REFERENCE"));
|
assertTrue(hasCategory(result, "CONCURRENCY"));
|
}
|
|
@Test
|
public void blocksRecordWhoseConfiguredSourceSnapshotWasNotInitialized() {
|
arrangeRecord("item-1", "legacy value", "legacy value", 0,
|
"SUCCESS", "PRIMARY", "field-1");
|
when(versionMapper.selectById(anyString())).thenAnswer(invocation -> {
|
String id = invocation.getArgument(0);
|
ElnFieldVersionEntity version = fieldVersion(id,
|
"version-result".equals(id) ? "TEXTAREA"
|
: "version-conclusion".equals(id) ? "SELECT" : "TEXT",
|
"version-result".equals(id) || "version-conclusion".equals(id) ? 1 : 0);
|
if ("version-1".equals(id)) {
|
version.setBangdingPeizhi("{\"read\":{\"source\":\"LIMS_TASK\","
|
+ "\"property\":\"verification.sample_name\",\"propertyRevision\":1}}");
|
}
|
return version;
|
});
|
|
RecordFreezeCheckResult result = service.prepare(request("item-1")).getItems().get(0);
|
|
assertEquals(RecordFreezeCheckResult.BLOCKED, result.getStatus());
|
assertTrue(result.getDiagnostics().toString(), result.getDiagnostics().stream().anyMatch(issue ->
|
"SOURCE_INITIALIZATION_INCOMPLETE".equals(issue.getCode())
|
&& "binding-1".equals(issue.getTargetBindingId())
|
&& "field-1".equals(issue.getTargetFieldCode())));
|
}
|
|
@Test
|
public void marksMissingConfiguredSourceValueAsInitializationIncomplete() {
|
arrangeRecord("item-1", "legacy value", "legacy value", 0,
|
"SUCCESS", "PRIMARY", "field-1");
|
when(valueMapper.selectList(any())).thenReturn(Arrays.asList(
|
value("binding-result", "version-result",
|
ElnTestResultFields.RESULT, "ELN 检验结果"),
|
value("binding-conclusion", "version-conclusion",
|
ElnTestResultFields.CONCLUSION, "compliant")));
|
when(versionMapper.selectById(anyString())).thenAnswer(invocation -> {
|
String id = invocation.getArgument(0);
|
ElnFieldVersionEntity version = fieldVersion(id,
|
"version-result".equals(id) ? "TEXTAREA"
|
: "version-conclusion".equals(id) ? "SELECT" : "TEXT",
|
"version-result".equals(id) || "version-conclusion".equals(id) ? 1 : 0);
|
if ("version-1".equals(id)) {
|
version.setBangdingPeizhi("{\"read\":{\"source\":\"LIMS_TASK\","
|
+ "\"property\":\"verification.sample_name\",\"propertyRevision\":1}}");
|
}
|
return version;
|
});
|
|
RecordFreezeCheckResult result = service.prepare(request("item-1")).getItems().get(0);
|
|
assertEquals(RecordFreezeCheckResult.BLOCKED, result.getStatus());
|
assertTrue(result.getDiagnostics().toString(), result.getDiagnostics().stream().anyMatch(issue ->
|
"SOURCE_INITIALIZATION_INCOMPLETE".equals(issue.getCode())
|
&& "binding-1".equals(issue.getTargetBindingId())
|
&& "field-1".equals(issue.getTargetFieldCode())));
|
}
|
|
@Test
|
public void allowsRequiredConfiguredDecimalSnapshotToFreeze() {
|
arrangeConfiguredStructuredValue("DECIMAL", "12.34",
|
new BigDecimal("12.340"), null);
|
|
RecordFreezeCheckResult result = service.prepare(request("item-1")).getItems().get(0);
|
|
assertEquals(result.getDiagnostics().toString(), RecordFreezeCheckResult.READY, result.getStatus());
|
}
|
|
@Test
|
public void allowsRequiredConfiguredDateSnapshotToFreeze() {
|
arrangeConfiguredStructuredValue("DATE", "2026-09-07", null,
|
java.sql.Date.valueOf("2026-09-07"));
|
|
RecordFreezeCheckResult result = service.prepare(request("item-1")).getItems().get(0);
|
|
assertEquals(result.getDiagnostics().toString(), RecordFreezeCheckResult.READY, result.getStatus());
|
}
|
|
@Test
|
public void blocksAllDriftedCrossTemplateSnapshotsWithoutWritingTargetValues() {
|
arrangeRecord("item-1", "expected", "expected", 0, "SUCCESS", "PRIMARY", "field-1");
|
ElnCrossTemplateSnapshotResolver.SnapshotIssue first =
|
new ElnCrossTemplateSnapshotResolver.SnapshotIssue("SOURCE_VALUE_DRIFT",
|
"源字段值已变化", "binding-1", "field-1", "SOURCE-A");
|
ElnCrossTemplateSnapshotResolver.SnapshotIssue second =
|
new ElnCrossTemplateSnapshotResolver.SnapshotIssue("SOURCE_REVISION_DRIFT",
|
"源记录当前修订已变化", "binding-2", "field-2", "SOURCE-B");
|
when(crossTemplateSnapshotResolver.validatePersistedSnapshots(
|
eq("tenant-1"), eq("item-1"), any()))
|
.thenReturn(Arrays.asList(first, second));
|
|
RecordFreezeCheckResult result = service.prepare(request("item-1")).getItems().get(0);
|
|
assertEquals(RecordFreezeCheckResult.BLOCKED, result.getStatus());
|
assertEquals(2, result.getDiagnostics().stream()
|
.filter(issue -> "CROSS_TEMPLATE".equals(issue.getCategory())).count());
|
assertTrue(result.getDiagnostics().stream().anyMatch(issue -> "binding-1".equals(issue.getTargetBindingId())
|
&& "field-1".equals(issue.getTargetFieldCode())
|
&& "SOURCE-A".equals(issue.getSourceTemplateCode())));
|
verify(valueMapper, never()).updateById(any(ElnRecordFieldValueEntity.class));
|
}
|
|
@Test
|
public void permitsNonRequiredMissingFormulaInputButBlocksRecalculatedDocxMismatch() {
|
arrangeRecord("item-1", "expected", "expected", 0, "MISSING_INPUT", "PRIMARY", "field-1");
|
when(calculation.recalculateAll(anyString(), any(), any(), any(), anyString(), anyString())).thenReturn(Collections.emptyList());
|
RecordFreezeCheckResult ready = service.prepare(request("item-1")).getItems().get(0);
|
assertEquals(ready.getDiagnostics().toString(), RecordFreezeCheckResult.READY, ready.getStatus());
|
assertFalse(ready.getDiagnostics().get(0).isBlocking());
|
|
arrangeRecord("item-1", "old", "different", 0, "SUCCESS", "PRIMARY", "field-1");
|
RecordFreezeCheckResult blocked = service.prepare(request("item-1")).getItems().get(0);
|
assertEquals(RecordFreezeCheckResult.BLOCKED, blocked.getStatus());
|
}
|
|
@Test
|
public void blocksFormulaWhenItsActiveResultBindingOrCurrentValueIsMissing() {
|
arrangeRecord("item-1", "expected", "expected", 0, "SUCCESS", "PRIMARY", "field-1");
|
ElnTemplateFormulaBindingEntity formula = new ElnTemplateFormulaBindingEntity();
|
formula.setId("formula-1");
|
formula.setMubanId("template-1");
|
formula.setBangdingZhuangtai("ACTIVE");
|
formula.setJieguoBangdingId("missing-result-binding");
|
when(formulaBindingMapper.selectList(any())).thenReturn(Collections.singletonList(formula));
|
when(calculation.recalculateAll(anyString(), any(), any(), any(), anyString(), anyString())).thenReturn(Collections.emptyList());
|
|
RecordFreezeCheckResult result = service.prepare(request("item-1")).getItems().get(0);
|
|
assertEquals(RecordFreezeCheckResult.BLOCKED, result.getStatus());
|
assertTrue(result.getDiagnostics().stream().anyMatch(issue -> "FORMULA".equals(issue.getCategory())
|
&& issue.getCode().equals("FORMULA_RESULT_BINDING_INVALID")));
|
}
|
|
@Test
|
public void blocksRequiredRepeatFormulaWhenAnActiveRowIsMissingInput() {
|
ElnRecordRepeatValueEntity repeatValue = repeatFormulaValue("MISSING_INPUT", null);
|
repeatValue.setJisuanZhuangtai("MISSING_INPUT");
|
ElnRecordFormulaCalculationResult calculationResult =
|
new ElnRecordFormulaCalculationResult();
|
calculationResult.setRepeatRows(Collections.singletonList(repeatRow()));
|
calculationResult.setRepeatValues(Collections.singletonList(repeatValue));
|
arrangeRequiredRepeatFormula(calculationResult, "");
|
|
RecordFreezeCheckResult result = service.prepare(request("item-1")).getItems().get(0);
|
|
assertEquals(RecordFreezeCheckResult.BLOCKED, result.getStatus());
|
assertTrue(result.getDiagnostics().stream().anyMatch(issue ->
|
"REQUIRED_REPEAT_FORMULA_NOT_SUCCESS".equals(issue.getCode())));
|
}
|
|
@Test
|
public void blocksWhenRequiredRepeatFormulaCellIsMissingForActiveRow() {
|
ElnRecordFormulaCalculationResult calculationResult =
|
new ElnRecordFormulaCalculationResult();
|
calculationResult.setRepeatRows(Collections.singletonList(repeatRow()));
|
arrangeRequiredRepeatFormula(calculationResult, "");
|
|
RecordFreezeCheckResult result = service.prepare(request("item-1")).getItems().get(0);
|
|
assertEquals(RecordFreezeCheckResult.BLOCKED, result.getStatus());
|
assertTrue(result.getDiagnostics().stream().anyMatch(issue ->
|
"REPEAT_FORMULA_RESULT_MISSING".equals(issue.getCode())));
|
}
|
|
@Test
|
public void blocksWhenRecalculatedRepeatFormulaDiffersFromDocx() {
|
ElnRecordFormulaCalculationResult calculationResult =
|
new ElnRecordFormulaCalculationResult();
|
calculationResult.setRepeatRows(Collections.singletonList(repeatRow()));
|
calculationResult.setRepeatValues(Collections.singletonList(
|
repeatFormulaValue("SUCCESS", "expected")));
|
arrangeRequiredRepeatFormula(calculationResult, "tampered");
|
|
RecordFreezeCheckResult result = service.prepare(request("item-1")).getItems().get(0);
|
|
assertEquals(RecordFreezeCheckResult.BLOCKED, result.getStatus());
|
assertTrue(result.getDiagnostics().stream().anyMatch(issue ->
|
"DOCX_REPEAT_FORMULA_VALUE_MISMATCH".equals(issue.getCode())));
|
}
|
|
private void arrangeRequiredRepeatFormula(
|
ElnRecordFormulaCalculationResult calculationResult, String runtimeDocxValue) {
|
arrangeRecord("item-1", "expected", "expected", 0,
|
"SUCCESS", "PRIMARY", "field-1");
|
ElnTemplateBindingEntity repeatResult = binding("repeat-result", "REPEAT",
|
"eln.repeat.group-a.prototype.repeat-result", "repeat-result");
|
repeatResult.setRepeatGroupCode("group-a");
|
repeatResult.setZiduanBanbenId("repeat-version");
|
ElnTemplateBindingEntity testResult = binding("binding-result", "PRIMARY",
|
"eln.field.test.result", ElnTestResultFields.RESULT);
|
testResult.setZiduanBanbenId("version-result");
|
ElnTemplateBindingEntity conclusion = binding("binding-conclusion", "PRIMARY",
|
"eln.field.test.conclusion", ElnTestResultFields.CONCLUSION);
|
conclusion.setZiduanBanbenId("version-conclusion");
|
when(bindingMapper.selectList(any())).thenReturn(Arrays.asList(
|
binding("binding-1", "PRIMARY", "eln.field.field", "field-1"),
|
testResult, conclusion, repeatResult));
|
when(formulaBindingMapper.selectList(any())).thenReturn(Collections.singletonList(
|
formula("repeat-formula", "repeat-result")));
|
when(versionMapper.selectById(anyString())).thenAnswer(invocation -> {
|
String id = invocation.getArgument(0);
|
if ("repeat-version".equals(id)) return fieldVersion(id, "TEXT", 1);
|
if ("version-result".equals(id)) return fieldVersion(id, "TEXTAREA", 1);
|
if ("version-conclusion".equals(id)) return fieldVersion(id, "SELECT", 1);
|
return fieldVersion(id, "TEXT", 0);
|
});
|
when(evidence.readControls("tenant-1", "record.docx")).thenReturn(Arrays.asList(
|
new DocxControlSnapshot("eln.field.field", "", "", "TEXT", "PRIMARY",
|
"word/document.xml", "", Collections.emptyMap(), "expected"),
|
new DocxControlSnapshot("eln.field.test.result", "", "", "TEXTAREA",
|
"PRIMARY", "word/document.xml", "", Collections.emptyMap(), "ELN 检验结果"),
|
new DocxControlSnapshot("eln.field.test.conclusion", "", "", "SELECT",
|
"PRIMARY", "word/document.xml", "", Collections.emptyMap(), "compliant"),
|
new DocxControlSnapshot("eln.repeat.group-a.prototype.repeat-result", "", "",
|
"TEXT", "REPEAT", "word/document.xml", "", Collections.emptyMap(), ""),
|
new DocxControlSnapshot("eln.repeat.group-a.row-1.repeat-result", "", "",
|
"TEXT", "REPEAT", "word/document.xml", "", Collections.emptyMap(),
|
runtimeDocxValue)));
|
when(calculation.recalculateAllWithRepeats(anyString(), any(), any(), any(),
|
anyString(), anyString())).thenReturn(calculationResult);
|
when(repeatValueMapper.updateById(any(ElnRecordRepeatValueEntity.class))).thenReturn(1);
|
}
|
|
private static ElnRecordRepeatRowEntity repeatRow() {
|
ElnRecordRepeatRowEntity row = new ElnRecordRepeatRowEntity();
|
row.setRepeatGroupCode("group-a");
|
row.setRowId("row-1");
|
row.setOperationStatus("ACTIVE");
|
row.setFDeleteMark(0);
|
return row;
|
}
|
|
private static ElnRecordRepeatValueEntity repeatFormulaValue(String status, String text) {
|
ElnRecordRepeatValueEntity value = new ElnRecordRepeatValueEntity();
|
value.setRepeatGroupCode("group-a");
|
value.setRepeatRowId("row-1");
|
value.setMubanBangdingId("repeat-result");
|
value.setZiduanBanbenId("repeat-version");
|
value.setZiduanBianma("repeat-result");
|
value.setZhiWenben(text);
|
value.setJisuanZhuangtai(status);
|
return value;
|
}
|
|
private void arrangeRecord(String itemId, String storedValue, String docxValue, int required,
|
String formulaStatus, String controlRole, String fieldCode) {
|
ElnRecordEntity record = new ElnRecordEntity();
|
record.setId("record-1"); record.setJianyanXiangId(itemId); record.setDangqianXiudingId("revision-1");
|
record.setMubanId("template-1"); record.setFVersion(1);
|
ElnRecordRevisionEntity revision = new ElnRecordRevisionEntity();
|
revision.setId("revision-1"); revision.setDianziJiluId("record-1"); revision.setBizStatus("DRAFT"); revision.setJiluWendang("record.docx");
|
ElnRecordFieldValueEntity value = new ElnRecordFieldValueEntity();
|
value.setMubanBangdingId("binding-1"); value.setZiduanBanbenId("version-1"); value.setZiduanBianma(fieldCode);
|
value.setZhiWenben(storedValue); value.setJisuanZhuangtai(formulaStatus);
|
ElnRecordFieldValueEntity testResult = value("binding-result", "version-result",
|
ElnTestResultFields.RESULT, "ELN 检验结果");
|
ElnRecordFieldValueEntity testConclusion = value("binding-conclusion", "version-conclusion",
|
ElnTestResultFields.CONCLUSION, "compliant");
|
ElnFieldVersionEntity version = new ElnFieldVersionEntity();
|
version.setId("version-1"); version.setFTenantId("tenant-1"); version.setShujuLeixing("TEXT"); version.setShifouBitian(required);
|
when(recordMapper.selectLiveByTestWorkItem("tenant-1", itemId)).thenReturn(record);
|
when(recordMapper.selectLiveForUpdate("tenant-1", "record-1")).thenReturn(record);
|
when(revisionMapper.selectOne(any())).thenReturn(revision);
|
when(valueMapper.selectList(any())).thenReturn(Arrays.asList(value, testResult, testConclusion));
|
when(operationMapper.selectCount(any())).thenReturn(0L);
|
ElnTemplateBindingEntity resultBinding = binding("binding-result", "PRIMARY",
|
"eln.field.test.result", ElnTestResultFields.RESULT);
|
resultBinding.setZiduanBanbenId("version-result");
|
ElnTemplateBindingEntity conclusionBinding = binding("binding-conclusion", "PRIMARY",
|
"eln.field.test.conclusion", ElnTestResultFields.CONCLUSION);
|
conclusionBinding.setZiduanBanbenId("version-conclusion");
|
when(bindingMapper.selectList(any())).thenReturn(Arrays.asList(
|
binding("binding-1", "PRIMARY", "eln.field.field", fieldCode), resultBinding, conclusionBinding));
|
when(formulaBindingMapper.selectList(any())).thenReturn(Collections.singletonList(
|
formula("formula-1", "binding-1")));
|
when(versionMapper.selectById(anyString())).thenAnswer(invocation -> {
|
String id = invocation.getArgument(0);
|
if ("version-result".equals(id)) return fieldVersion(id, "TEXTAREA", 1);
|
if ("version-conclusion".equals(id)) return fieldVersion(id, "SELECT", 1);
|
return version;
|
});
|
when(evidence.readControls("tenant-1", "record.docx")).thenReturn(Arrays.asList(
|
new DocxControlSnapshot("eln.field.field", "", "", "TEXT", controlRole, "word/document.xml", "", Collections.emptyMap(), docxValue),
|
new DocxControlSnapshot("eln.field.test.result", "", "", "TEXTAREA", "PRIMARY", "word/document.xml", "", Collections.emptyMap(), "ELN 检验结果"),
|
new DocxControlSnapshot("eln.field.test.conclusion", "", "", "SELECT", "PRIMARY", "word/document.xml", "", Collections.emptyMap(), "compliant")));
|
when(recordMapper.advanceVersion("tenant-1", "record-1", 1, "user-1")).thenReturn(1);
|
when(valueMapper.updateById(any(ElnRecordFieldValueEntity.class))).thenReturn(1);
|
when(fence.acquireForOperation(anyString(), anyString(), anyString(), anyString(), anyString())).thenAnswer(invocation -> response("freeze:" + invocation.getArgument(4)));
|
when(fence.release(anyString(), anyString(), anyString(), anyString(), anyString())).thenReturn(response(true));
|
}
|
|
private void arrangeConfiguredStructuredValue(String type, String docxValue,
|
BigDecimal number, Date date) {
|
arrangeRecord("item-1", null, docxValue, 1, "SUCCESS", "PRIMARY", "field-1");
|
ElnRecordFieldValueEntity value = valueMapper.selectList(null).get(0);
|
value.setZhiShuzhi(number);
|
value.setZhiRiqi(date);
|
value.setZhiLaiyuan("LIMS_TASK");
|
value.setYuanShuxing("configured.value");
|
value.setYuanShuxingBanben(1);
|
value.setYuanQuzhiZhuangtai("SUCCESS");
|
value.setYuanXueyuan("configured.dataset@1/value");
|
value.setYuanHuoquShijian(java.sql.Timestamp.valueOf("2026-09-07 10:00:00"));
|
when(versionMapper.selectById(anyString())).thenAnswer(invocation -> {
|
String id = invocation.getArgument(0);
|
ElnFieldVersionEntity version = fieldVersion(id,
|
"version-result".equals(id) ? "TEXTAREA"
|
: "version-conclusion".equals(id) ? "SELECT" : type,
|
1);
|
if ("version-1".equals(id)) {
|
version.setBangdingPeizhi("{\"read\":{\"source\":\"LIMS_TASK\","
|
+ "\"property\":\"configured.value\",\"propertyRevision\":1}}");
|
}
|
return version;
|
});
|
when(calculation.recalculateAll(anyString(), any(), any(), any(), anyString(), anyString()))
|
.thenReturn(Collections.emptyList());
|
}
|
|
private static ElnTemplateBindingEntity binding(String id, String role, String tag, String code) {
|
ElnTemplateBindingEntity binding = new ElnTemplateBindingEntity();
|
binding.setId(id); binding.setMubanId("template-1"); binding.setBangdingZhuangtai("ACTIVE");
|
binding.setKongjianJuese(role); binding.setKongjianBiaoqian(tag); binding.setKongjianLeixing(
|
ElnTestResultFields.RESULT.equals(code) ? "TEXTAREA"
|
: ElnTestResultFields.CONCLUSION.equals(code) ? "SELECT" : "TEXT");
|
binding.setZiduanDingyiId("definition-1"); binding.setZiduanBanbenId("version-1"); binding.setZiduanBianma(code);
|
return binding;
|
}
|
|
private static ElnRecordFieldValueEntity value(String bindingId, String versionId,
|
String code, String text) {
|
ElnRecordFieldValueEntity value = new ElnRecordFieldValueEntity();
|
value.setMubanBangdingId(bindingId);
|
value.setZiduanBanbenId(versionId);
|
value.setZiduanBianma(code);
|
value.setZhiWenben(text);
|
return value;
|
}
|
|
private static ElnFieldVersionEntity fieldVersion(String id, String type, int required) {
|
ElnFieldVersionEntity version = new ElnFieldVersionEntity();
|
version.setId(id);
|
version.setFTenantId("tenant-1");
|
version.setShujuLeixing(type);
|
version.setShifouBitian(required);
|
return version;
|
}
|
|
private static ElnTemplateFormulaBindingEntity formula(String id, String resultBindingId) {
|
ElnTemplateFormulaBindingEntity formula = new ElnTemplateFormulaBindingEntity();
|
formula.setId(id);
|
formula.setMubanId("template-1");
|
formula.setBangdingZhuangtai("ACTIVE");
|
formula.setJieguoBangdingId(resultBindingId);
|
return formula;
|
}
|
|
private static RecordFreezeCheckRequest request(String itemId) {
|
RecordFreezeCheckRequest request = new RecordFreezeCheckRequest();
|
request.setTenantId("tenant-1"); request.setUserId("user-1"); request.setOperationCode("op-1");
|
request.setTestWorkItemIds(Collections.singletonList(itemId));
|
return request;
|
}
|
|
private static boolean hasCategory(RecordFreezeCheckResult result, String category) {
|
return result.getDiagnostics().stream().anyMatch(issue -> category.equals(issue.getCategory()));
|
}
|
|
private static <T> ActionResult<T> response(T data) {
|
ActionResult<T> response = new ActionResult<>(); response.setCode(200); response.setData(data); return response;
|
}
|
}
|