package jnpf.dmsService;
|
import jnpf.base.UserInfo;
|
import jnpf.dmsEntity.fenfa.*;
|
import jnpf.dmsEntity.fenfa.DmsWenjianDayinFasongEntity.Batch;
|
import jnpf.dmsEntity.fenfa.form.DmsWenjianDayinFasongForm;
|
import jnpf.dmsMapper.*;
|
import jnpf.dmsPermission.DmsCurrentIdentity;
|
import jnpf.exception.DataException;
|
import jnpf.util.JsonUtil;
|
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.Test;
|
import java.util.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
import static org.mockito.Mockito.*;
|
|
class DmsWenjianDayinFasongServiceTest {
|
final DmsWenjianDayinHaomaService numbers = mock(DmsWenjianDayinHaomaService.class);
|
final DmsCurrentIdentity identity = mock(DmsCurrentIdentity.class);
|
final DmsWenjianFenfaMapper tasks = mock(DmsWenjianFenfaMapper.class);
|
final DmsWenjianDayinQuerenMapper mapper = mock(DmsWenjianDayinQuerenMapper.class);
|
final DmsWenjianDayinTaizhangService ledger = mock(DmsWenjianDayinTaizhangService.class);
|
final DmsWenjianFenfaService distribution = mock(DmsWenjianFenfaService.class);
|
final DmsWenjianDayinQuerenService service = new DmsWenjianDayinQuerenService(identity, tasks, mapper, ledger, distribution, numbers);
|
final DmsWenjianDayinFasongForm form = new DmsWenjianDayinFasongForm();
|
DmsWenjianDayinFasongEntity saved;
|
@BeforeEach void setup() throws Exception {
|
when(numbers.ensureTaskNumbers(anyString(), any(), anyInt())).thenAnswer(c -> java.util.stream.IntStream.rangeClosed(1, 7).mapToObj(i -> {
|
jnpf.dmsEntity.fenfa.DmsWenjianDayinHaoma n = new jnpf.dmsEntity.fenfa.DmsWenjianDayinHaoma(); n.setTaskSequence(i); n.setSerialNumber("S"+i); n.setCountSerialNumber("2026"+String.format("%04d",i)); return n;
|
}).toList());
|
UserInfo user = new UserInfo(); user.setUserId("user");
|
when(identity.requireUser()).thenReturn(user); when(identity.tenantId(user)).thenReturn("tenant");
|
form.setRequestId(UUID.randomUUID().toString()); form.setTaskId("task"); form.setFileVersionId("version"); form.setCopies(1);
|
DmsWenjianDayinRenwuEntity task = new DmsWenjianDayinRenwuEntity(); task.setDayinFenshu(7); task.setId("task");
|
when(tasks.selectPrintTaskForUpdate("tenant", "task")).thenReturn(task);
|
when(ledger.list(any(), isNull(), eq("f_id"), eq("task"))).thenReturn(List.of(Map.of("f_id", "task")));
|
DmsWenjianDayinQuerenEntity version = new DmsWenjianDayinQuerenEntity(); version.setFileVersionId("version");
|
when(mapper.selectTaskVersion("tenant", "task")).thenReturn(version);
|
when(mapper.insertAttempt(any())).thenAnswer(c -> { saved = c.getArgument(0); return 1; });
|
when(mapper.selectAttempt(eq("tenant"), anyString())).thenAnswer(c -> saved != null && saved.getId().equals(c.getArgument(1)) ? saved : null);
|
when(mapper.selectActiveAttempt("tenant", "task")).thenAnswer(c -> saved != null && !"CLOSED".equals(saved.getState()) ? saved : null);
|
when(mapper.updateAttempt(any())).thenAnswer(c -> { saved = c.getArgument(0); return 1; });
|
}
|
jnpf.dmsEntity.fenfa.form.DmsWenjianDayinYulanForm previewForm() {
|
var preview = new jnpf.dmsEntity.fenfa.form.DmsWenjianDayinYulanForm();
|
preview.setTaskId("task"); preview.setFileVersionId("version");
|
return preview;
|
}
|
@Test void previewUsesNextFixedNumberAndDoesNotCreateSendOrPrintRecords() {
|
when(tasks.maxPrintSequence("tenant", "task")).thenReturn(3);
|
var first = service.previewParameters(previewForm());
|
assertEquals("S4", first.getSerialNumber());
|
assertEquals("20260004", first.getCountSerialNumber());
|
assertEquals(first, service.previewParameters(previewForm()));
|
verify(mapper, never()).insertAttempt(any()); verify(mapper, never()).insertConfirmation(any());
|
verifyNoInteractions(distribution);
|
}
|
@Test void previewRejectsUnauthorizedOrChangedVersionBeforeAllocating() {
|
when(ledger.list(any(), isNull(), eq("f_id"), eq("task"))).thenReturn(List.of());
|
assertThrows(DataException.class, () -> service.previewParameters(previewForm()));
|
when(ledger.list(any(), isNull(), eq("f_id"), eq("task"))).thenReturn(List.of(Map.of("f_id", "task")));
|
var preview = previewForm(); preview.setFileVersionId("other-version");
|
assertThrows(DataException.class, () -> service.previewParameters(preview));
|
verifyNoInteractions(numbers, distribution);
|
}
|
@Test void previewPreservesActiveAndConfirmedAttemptNumberWithoutAllocating() {
|
service.prepare(form); clearInvocations(numbers);
|
when(tasks.maxPrintSequence("tenant", "task")).thenReturn(1);
|
assertEquals("S1", service.previewParameters(previewForm()).getSerialNumber());
|
saved.setState("CONFIRMED");
|
assertEquals("S1", service.previewParameters(previewForm()).getSerialNumber());
|
saved.setUserId("other");
|
assertThrows(DataException.class, () -> service.previewParameters(previewForm()));
|
verifyNoInteractions(numbers, distribution);
|
}
|
@Test void previewRejectsCompletedMissingAndDamagedTasks() {
|
when(tasks.countConsumedPrints("tenant", "task")).thenReturn(7);
|
assertThrows(DataException.class, () -> service.previewParameters(previewForm()));
|
verifyNoInteractions(numbers);
|
when(tasks.countConsumedPrints("tenant", "task")).thenReturn(0);
|
when(numbers.ensureTaskNumbers(anyString(), any(), anyInt())).thenReturn(List.of());
|
assertThrows(DataException.class, () -> service.previewParameters(previewForm()));
|
when(tasks.selectPrintTaskForUpdate("tenant", "task")).thenReturn(null);
|
assertThrows(DataException.class, () -> service.previewParameters(previewForm()));
|
assertThrows(DataException.class, () -> service.previewParameters(null));
|
verify(mapper, never()).insertAttempt(any()); verifyNoInteractions(distribution);
|
}
|
Batch batch(int... pages) {
|
Batch b = new Batch(); b.setId(UUID.randomUUID().toString()); b.setItems(List.of(0));
|
b.setPages(Arrays.stream(pages).boxed().toList()); return b;
|
}
|
void planned() throws Exception {
|
service.prepare(form); form.setBatches(List.of(batch(1), batch(2))); service.plan(form);
|
form.setBatchId(form.getBatches().get(0).getId()); form.setToken(UUID.randomUUID().toString());
|
}
|
@Test void refreshRestoresFrozenCopiesWithoutNewAttempt() throws Exception {
|
service.prepare(form); String original = saved.getId();
|
form.setRequestId(UUID.randomUUID().toString()); form.setCopies(7);
|
assertEquals(original, service.prepare(form).getId()); assertEquals(1, saved.getCopies());
|
verify(mapper, times(1)).insertAttempt(any()); verifyNoInteractions(distribution);
|
}
|
@Test void anotherActorCannotTakeOver() throws Exception {
|
service.prepare(form); saved.setUserId("other");
|
assertThrows(DataException.class, () -> service.prepare(form)); assertThrows(DataException.class, () -> service.begin(form));
|
}
|
@Test void twoCopiesRequireFullSeparatePlansAndFreezeNextTaskNumbers() throws Exception {
|
form.setCopies(2);
|
when(tasks.maxPrintSequence("tenant", "task")).thenReturn(3);
|
service.prepare(form);
|
var frozen = JsonUtil.getJsonToList(saved.getNumbersJson(), DmsWenjianDayinHaoma.class);
|
assertEquals(List.of(4,5), frozen.stream().map(DmsWenjianDayinHaoma::getTaskSequence).toList());
|
Batch first = batch(1,2), shortSecond = batch(1); shortSecond.setItems(List.of(1));
|
form.setBatches(List.of(first,shortSecond));
|
assertThrows(DataException.class, () -> service.plan(form));
|
Batch second = batch(1,2); second.setItems(List.of(1));
|
form.setBatches(List.of(first,second)); service.plan(form);
|
assertEquals(2, JsonUtil.getJsonToList(saved.getBatchesJson(), Batch.class).size());
|
}
|
|
@Test void sameBatchCannotBeClaimedTwiceEvenWithSameToken() throws Exception {
|
planned(); service.begin(form); assertThrows(DataException.class, () -> service.begin(form));
|
form.setToken(UUID.randomUUID().toString()); assertThrows(DataException.class, () -> service.begin(form)); verifyNoInteractions(distribution);
|
}
|
@Test void lateReceiptMustMatchTokenAndIsIdempotent() throws Exception {
|
planned(); service.begin(form); String token = form.getToken();
|
form.setToken(UUID.randomUUID().toString()); assertThrows(DataException.class, () -> service.submitted(form));
|
form.setToken(token); service.submitted(form); service.submitted(form);
|
assertEquals("SUBMITTED", JsonUtil.getJsonToList(saved.getBatchesJson(), Batch.class).get(0).getState());
|
assertThrows(DataException.class, () -> service.finish(form));
|
}
|
@Test void cannotSkipBatchOrChangeFrozenCopies() throws Exception {
|
planned(); form.setBatchId(form.getBatches().get(1).getId()); assertThrows(DataException.class, () -> service.begin(form));
|
form.setCopies(3); assertThrows(DataException.class, () -> service.plan(form));
|
}
|
@Test void planCannotSkipPagesAndSentBatchCannotSplit() throws Exception {
|
service.prepare(form); form.setBatches(List.of(batch(1, 3))); assertThrows(DataException.class, () -> service.plan(form));
|
form.setBatches(List.of(batch(1, 2))); service.plan(form);
|
form.setBatchId(form.getBatches().get(0).getId()); form.setToken(UUID.randomUUID().toString()); service.begin(form);
|
form.setBatches(List.of(batch(1), batch(2))); assertThrows(DataException.class, () -> service.split(form));
|
}
|
@Test void splitPreservesPreviousSubmittedProgress() throws Exception {
|
service.prepare(form); form.setBatches(List.of(batch(1), batch(2, 3))); service.plan(form);
|
form.setBatchId(form.getBatches().get(0).getId()); form.setToken(UUID.randomUUID().toString()); service.begin(form); service.submitted(form);
|
form.setBatchId(form.getBatches().get(1).getId()); form.setBatches(List.of(batch(2), batch(3))); service.split(form);
|
List<Batch> restored = JsonUtil.getJsonToList(saved.getBatchesJson(), Batch.class);
|
assertEquals(3, restored.size()); assertEquals("SUBMITTED", restored.get(0).getState()); assertEquals(List.of(2), restored.get(1).getPages());
|
}
|
@Test void permissionChangeAfterPreparationPreventsDispatch() throws Exception {
|
planned(); when(ledger.list(any(), isNull(), eq("f_id"), eq("task"))).thenReturn(List.of());
|
assertThrows(DataException.class, () -> service.begin(form));
|
assertEquals("READY", JsonUtil.getJsonToList(saved.getBatchesJson(), Batch.class).get(0).getState());
|
}
|
}
|