package jnpf.dmsService;
|
|
import jnpf.base.UserInfo;
|
import jnpf.audit.sdk.annotation.AuditLog;
|
import jnpf.dmsEntity.fenfa.*;
|
import jnpf.dmsEntity.fenfa.vo.*;
|
import jnpf.dmsMapper.*;
|
import jnpf.dmsPermission.DmsCurrentIdentity;
|
import jnpf.exception.DataException;
|
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.mockito.*;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.springframework.transaction.annotation.Transactional;
|
import java.util.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
import static org.mockito.Mockito.*;
|
import static org.mockito.ArgumentMatchers.*;
|
|
@ExtendWith(MockitoExtension.class)
|
class DmsWenjianBupinghengServiceTest {
|
@Mock jnpf.dmsIntegration.audit.DmsSystemAudit systemAudit;
|
@Mock DmsCurrentIdentity identity;
|
@Mock DmsWenjianFenfaMapper fenfa;
|
@Mock DmsWenjianBupinghengMapper mapper;
|
@Mock private jnpf.dmsService.DmsWenjianDayinHaomaService numbers;
|
@Mock private jnpf.dmsService.DmsWenjianChongdaGuard reprintGuard;
|
@InjectMocks DmsWenjianBupinghengService service;
|
|
void user() throws Exception {
|
UserInfo u=new UserInfo();u.setUserId("operator");u.setTenantId("tenant");
|
when(identity.requireUser()).thenReturn(u);when(identity.tenantId(u)).thenReturn("tenant");
|
}
|
DmsWenjianBupinghengExecution document(String... measures) throws Exception {
|
user();DmsWenjianBupinghengExecution doc=new DmsWenjianBupinghengExecution();doc.setId("doc");doc.setBizSign("signed");
|
when(mapper.lockDocument("tenant","doc")).thenReturn(doc);
|
List<DmsWenjianBupinghengExecution.Item> items=new ArrayList<>();
|
for(int i=0;i<measures.length;i++){
|
DmsWenjianBupinghengExecution.Item item=new DmsWenjianBupinghengExecution.Item();
|
item.setId("detail-"+i);item.setDayinJiluId("copy-"+i);item.setCuoshi(measures[i]);item.setYuanyin("破损");items.add(item);
|
}
|
when(mapper.lockItems("tenant","doc")).thenReturn(items);return doc;
|
}
|
void copy(int index,String status){
|
DmsWenjianDayinJiluEntity c=new DmsWenjianDayinJiluEntity();c.setId("copy-"+index);c.setDayinRenwuId("task");c.setBizStatus(status);
|
when(fenfa.selectPrintForUpdate("tenant",c.getId(),null)).thenReturn(c);
|
}
|
void task(){
|
DmsWenjianFenfaRenwuEntity d=new DmsWenjianFenfaRenwuEntity();d.setBizStatus("daifafang");
|
when(fenfa.selectDistributionTaskByPrintTaskForUpdate("tenant","task")).thenReturn(d);
|
DmsWenjianDayinRenwuEntity t=new DmsWenjianDayinRenwuEntity();t.setId("task");t.setTenantId("tenant");
|
t.setWenjianId("file");t.setWenjianMingcheng("历史快照");t.setBanbenhao("D(04)");t.setJieshouBumenId("department");t.setDayinFenshu(9);t.setBizStatus("yidayin");
|
when(fenfa.selectPrintTaskForUpdate("tenant","task")).thenReturn(t);
|
}
|
void success(){
|
when(mapper.voidPrint(eq("tenant"),anyString(),eq("operator"),any())).thenReturn(1);
|
when(mapper.completeDocument(eq("tenant"),eq("doc"),any())).thenReturn(1);
|
}
|
@Test void activeReprintStopsVoidBeforeSideEffects() throws Exception {
|
document("cuoshi2");copy(0,"daifafang");
|
doThrow(new DataException("locked")).when(reprintGuard).requireUnlocked("tenant","copy-0");
|
assertThrows(DataException.class,()->service.execute("doc"));
|
verify(mapper,never()).voidPrint(any(),any(),any(),any());
|
verify(mapper,never()).completeDocument(any(),any(),any());
|
verify(fenfa,never()).insertPrintTaskIfAbsent(any());
|
}
|
@Test void executesPersistedItemsAndLinksReplacementToNativeIds() throws Exception {
|
document("cuoshi1","cuoshi2");copy(0,"daifafang");copy(1,"daiqianshou");task();success();
|
when(fenfa.insertPrintTaskIfAbsent(any())).thenReturn(1);
|
when(mapper.linkReplacement(eq("tenant"),eq("detail-0"),eq("doc"),anyString())).thenReturn(1);
|
List<DmsWenjianBupinghengResultVO> r=service.execute("doc");
|
ArgumentCaptor<DmsWenjianDayinRenwuEntity> cap=ArgumentCaptor.forClass(DmsWenjianDayinRenwuEntity.class);
|
verify(fenfa).insertPrintTaskIfAbsent(cap.capture());DmsWenjianDayinRenwuEntity t=cap.getValue();
|
assertEquals("doc",t.getLaiyuanDanjuId());assertEquals("detail-0",t.getLaiyuanMingxiId());assertEquals("wenjian_bupingheng",t.getLaiyuanLeixing());
|
assertEquals(1,t.getDayinFenshu());assertEquals("daidayin",t.getBizStatus());assertEquals("历史快照",t.getWenjianMingcheng());assertEquals("D(04)",t.getBanbenhao());
|
assertEquals(t.getId(),r.get(0).getXinDayinRenwuId());assertNull(r.get(1).getXinDayinRenwuId());
|
verify(fenfa,never()).insertPrintRecord(any());verify(fenfa,never()).insertDistributionTaskIfAbsent(any());
|
InOrder order=inOrder(mapper);order.verify(mapper).lockDocument("tenant","doc");order.verify(mapper).lockItems("tenant","doc");
|
order.verify(mapper).voidPrint(eq("tenant"),eq("copy-0"),eq("operator"),any());
|
order.verify(mapper).linkReplacement(eq("tenant"),eq("detail-0"),eq("doc"),eq(t.getId()));
|
order.verify(mapper).voidPrint(eq("tenant"),eq("copy-1"),eq("operator"),any());
|
order.verify(mapper).finishDistribution(eq("tenant"),eq("task"),eq("operator"),any());order.verify(mapper).completeDocument(eq("tenant"),eq("doc"),any());
|
}
|
@Test void measureTwoOnlyVoidsCopy() throws Exception {
|
document("cuoshi2");copy(0,"daifafang");task();success();service.execute("doc");
|
verify(fenfa,never()).insertPrintTaskIfAbsent(any());verify(mapper,never()).linkReplacement(any(),any(),any(),any());
|
}
|
@Test void repeatedCompletedDocumentDoesNotMutateBusinessObjects() throws Exception {
|
DmsWenjianBupinghengExecution d=document("cuoshi1");d.setZhixingShijian(new Date());
|
mapper.lockItems("tenant","doc").get(0).setXinDayinRenwuId("replacement");
|
assertEquals("replacement",service.execute("doc").get(0).getXinDayinRenwuId());
|
verifyNoInteractions(fenfa);verify(mapper,never()).voidPrint(any(),any(),any(),any());verify(mapper,never()).completeDocument(any(),any(),any());
|
}
|
@Test void missingOrCrossTenantDocumentCannotExecute() throws Exception {
|
user();assertThrows(DataException.class,()->service.execute("doc"));verifyNoInteractions(fenfa);verify(mapper,never()).lockItems(any(),any());
|
}
|
@Test void unsignedNativeDocumentCannotExecute() throws Exception {
|
user();DmsWenjianBupinghengExecution d=new DmsWenjianBupinghengExecution();
|
when(mapper.lockDocument("tenant","doc")).thenReturn(d);
|
assertThrows(DataException.class,()->service.execute("doc"));verifyNoInteractions(fenfa);
|
}
|
@Test void invalidStoredMeasureCannotExecute() throws Exception {
|
document("unknown");assertThrows(DataException.class,()->service.execute("doc"));verifyNoInteractions(fenfa);
|
}
|
@Test void duplicateStoredCopiesCannotExecute() throws Exception {
|
document("cuoshi1","cuoshi2");mapper.lockItems("tenant","doc").get(1).setDayinJiluId("copy-0");
|
assertThrows(DataException.class,()->service.execute("doc"));verifyNoInteractions(fenfa);
|
}
|
@Test void staleCopyRejectsAllBeforeMutation() throws Exception {
|
document("cuoshi1","cuoshi2");copy(0,"daifafang");copy(1,"yiguidang");
|
assertThrows(DataException.class,()->service.execute("doc"));verify(mapper,never()).voidPrint(any(),any(),any(),any());
|
}
|
@Test void compareAndSetFailureDoesNotMarkExecuted() throws Exception {
|
document("cuoshi2");copy(0,"daifafang");task();
|
assertThrows(DataException.class,()->service.execute("doc"));verify(mapper,never()).completeDocument(any(),any(),any());
|
}
|
@Test void receiptFailureThrowsAndTransactionCoversAllBusinessEffects() throws Exception {
|
document("cuoshi2");copy(0,"daifafang");task();when(mapper.voidPrint(any(),any(),any(),any())).thenReturn(1);
|
assertThrows(DataException.class,()->service.execute("doc"));
|
java.lang.reflect.Method method=DmsWenjianBupinghengService.class.getMethod("execute",String.class);
|
assertTrue(Arrays.asList(method.getAnnotation(Transactional.class).rollbackFor()).contains(Exception.class));
|
assertEquals("#p0",method.getAnnotation(AuditLog.class).targetIdExpr());
|
}
|
@Test void scheduledExecutionUsesSystemZeroAndOriginalTenantAndSignature() throws Exception {
|
DmsWenjianBupinghengExecution d = new DmsWenjianBupinghengExecution();
|
d.setId("doc"); d.setBizSign("signed"); d.setDengjiRenId("registrar"); d.setVersion(3L);
|
when(mapper.lockDocument("tenant", "doc")).thenReturn(d);
|
DmsWenjianBupinghengExecution.Item item = new DmsWenjianBupinghengExecution.Item();
|
item.setId("detail-0"); item.setDayinJiluId("copy-0"); item.setCuoshi("cuoshi1"); item.setYuanyin("破损");
|
when(mapper.lockItems("tenant", "doc")).thenReturn(List.of(item));
|
copy(0, "daifafang"); task();
|
when(mapper.voidPrint(eq("tenant"), eq("copy-0"), eq("0"), any())).thenReturn(1);
|
when(mapper.completeDocument(eq("tenant"), eq("doc"), any())).thenReturn(1);
|
when(fenfa.insertPrintTaskIfAbsent(any())).thenReturn(1);
|
when(mapper.linkReplacement(eq("tenant"), eq("detail-0"), eq("doc"), any())).thenReturn(1);
|
service.executeScheduled("tenant", "doc", 3L);
|
verifyNoInteractions(identity);
|
ArgumentCaptor<DmsWenjianDayinRenwuEntity> replacement = ArgumentCaptor.forClass(DmsWenjianDayinRenwuEntity.class);
|
verify(fenfa).insertPrintTaskIfAbsent(replacement.capture());
|
assertEquals("0", replacement.getValue().getCreatorUserId());
|
assertEquals("tenant", replacement.getValue().getTenantId());
|
ArgumentCaptor<jnpf.audit.model.AuditEventDTO> event = ArgumentCaptor.forClass(jnpf.audit.model.AuditEventDTO.class);
|
verify(systemAudit).record(event.capture());
|
assertEquals("0", event.getValue().getOperatorId());
|
assertEquals("tenant", event.getValue().getTenantId());
|
assertEquals("signed", event.getValue().getRelatedSigns().get(0).getSignId());
|
assertTrue(event.getValue().getExtra().contains("registrar"));
|
}
|
@Test void scheduledExecutionRejectsChangedDocumentBeforeAnyEffects() throws Exception {
|
DmsWenjianBupinghengExecution d = new DmsWenjianBupinghengExecution();
|
d.setBizSign("signed"); d.setVersion(4L);
|
when(mapper.lockDocument("tenant", "doc")).thenReturn(d);
|
assertThrows(DataException.class, () -> service.executeScheduled("tenant", "doc", 3L));
|
verifyNoInteractions(identity, fenfa, systemAudit);
|
verify(mapper, never()).lockItems(any(), any());
|
}
|
@Test void scheduledExecutionRequiresExplicitTenantAndVersion() {
|
assertThrows(DataException.class, () -> service.executeScheduled("", "doc", 0L));
|
assertThrows(DataException.class, () -> service.executeScheduled("tenant", "doc", null));
|
verifyNoInteractions(mapper, identity, fenfa, systemAudit);
|
}
|
|
}
|