package jnpf.dmsService.impl; import jnpf.base.ActionResult; import jnpf.base.BillRuleApi; import jnpf.base.UserInfo; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import jnpf.audit.sdk.annotation.AuditLog; import jnpf.dms.DmsResourceApi; import jnpf.dmsEntity.DmsWenjianBanbenEntity; import jnpf.dmsEntity.permission.form.DmsPersonalFolderFileForm; import jnpf.dmsEntity.print.form.DmsWorkflowPrintFilesGrantForm; import jnpf.dmsEntity.print.vo.DmsWorkflowPrintFilesGrantResultVO; import jnpf.dmsEntity.preview.vo.DmsFilePageCountVO; import jnpf.dmsEntity.recordprint.DmsJiluDayinLiushuiEntity; import jnpf.dmsEntity.recordprint.DmsJiluDayinShenqingEntity; import jnpf.dmsEntity.recordprint.DmsJiluDayinShenqingZixiangEntity; import jnpf.dmsEntity.recordprint.form.DmsRecordPrintHuishouForm; import jnpf.dmsEntity.recordprint.form.DmsRecordPrintHuishouItemForm; import jnpf.dmsEntity.recordprint.form.DmsRecordPrintIssueForm; import jnpf.dmsEntity.recordprint.form.DmsRecordPrintIssueItemForm; import jnpf.dmsEntity.recordprint.vo.DmsRecordPrintConfirmVO; import jnpf.dmsEntity.recordprint.vo.DmsRecordPrintPrepareVO; import jnpf.dmsEntity.recordprint.vo.DmsRecordPrintSerialVO; import jnpf.dmsMapper.DmsRecordPrintItemMapper; import jnpf.dmsMapper.DmsRecordPrintRequestMapper; import jnpf.dmsMapper.DmsJiluDayinLiushuiMapper; import jnpf.dmsMapper.DmsWenjianBanbenMapper; import jnpf.dmsPermission.DmsCurrentIdentity; import jnpf.dmsService.DmsFilePageCountService; import jnpf.dmsService.recordprint.DmsRecordPrintPageParser; import jnpf.dmsService.recordprint.DmsRecordPrintProperties; import jnpf.dmsService.recordprint.DmsRecordPrintReservation; import jnpf.dmsService.recordprint.DmsRecordPrintReservationStore; import jnpf.exception.DataException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.apache.ibatis.builder.MapperBuilderAssistant; import org.apache.ibatis.session.Configuration; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import java.util.Date; import java.util.List; import java.util.UUID; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class DmsRecordPrintServiceImplTest { @Mock private DmsJiluDayinLiushuiMapper mapper; @Mock private DmsRecordPrintItemMapper itemMapper; @Mock private DmsRecordPrintRequestMapper requestMapper; @Mock private DmsWenjianBanbenMapper banbenMapper; @Mock private DmsResourceApi dmsResourceApi; @Mock private DmsCurrentIdentity identity; @Mock private BillRuleApi billRuleApi; @Mock private DmsFilePageCountService pageCountService; @Mock private DmsRecordPrintReservationStore reservationStore; private DmsRecordPrintServiceImpl service; @Test void completesPrintItemUsingEntity() { when(itemMapper.update(any(DmsJiluDayinShenqingZixiangEntity.class), any())) .thenReturn(1); service.complete(" item-1 "); ArgumentCaptor item = ArgumentCaptor.forClass(DmsJiluDayinShenqingZixiangEntity.class); verify(itemMapper).update(item.capture(), any()); assertEquals("dayin_wancheng", item.getValue().getDayinZhuangtai()); } @Test void rejectsMissingPrintItemOnCompletion() { when(itemMapper.update(any(DmsJiluDayinShenqingZixiangEntity.class), any())) .thenReturn(0); assertThrows(DataException.class, () -> service.complete("missing-item")); } /** * 初始化打印服务及当前登录用户。 */ @BeforeEach void setUp() throws Exception { if (TableInfoHelper.getTableInfo(DmsJiluDayinLiushuiEntity.class) == null) { TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new Configuration(), ""), DmsJiluDayinLiushuiEntity.class); } if (TableInfoHelper.getTableInfo(DmsJiluDayinShenqingZixiangEntity.class) == null) { TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new Configuration(), ""), DmsJiluDayinShenqingZixiangEntity.class); } DmsRecordPrintProperties properties = new DmsRecordPrintProperties(); service = new DmsRecordPrintServiceImpl(mapper, itemMapper, requestMapper, banbenMapper, dmsResourceApi, identity, billRuleApi, pageCountService, new DmsRecordPrintPageParser(), properties, reservationStore); } /** * 验证流程申请中的全部业务版本会被组装为永久打印授权。 */ @Test void authorizesAllRecordPrintVersionsForApplicant() { DmsJiluDayinShenqingEntity request = new DmsJiluDayinShenqingEntity(); request.setId("request-1"); request.setShenqingren(" user-1 "); DmsJiluDayinShenqingZixiangEntity first = new DmsJiluDayinShenqingZixiangEntity(); first.setBanbenId("version-1"); DmsJiluDayinShenqingZixiangEntity second = new DmsJiluDayinShenqingZixiangEntity(); second.setBanbenId("version-2"); DmsWenjianBanbenEntity firstVersion = businessVersion("version-1"); DmsWenjianBanbenEntity secondVersion = businessVersion("version-2"); DmsWorkflowPrintFilesGrantResultVO expected = new DmsWorkflowPrintFilesGrantResultVO(2, 2); ActionResult response = new ActionResult<>(); response.setCode(200); response.setData(expected); when(requestMapper.selectList(any())).thenReturn(List.of(request)); when(itemMapper.selectList(any())).thenReturn(List.of(first, second)); when(banbenMapper.selectList(any())).thenReturn(List.of(firstVersion, secondVersion)); when(dmsResourceApi.grantWorkflowPrintFiles(eq("jnpf-flowable"), any())) .thenReturn(response); DmsWorkflowPrintFilesGrantResultVO actual = service.authorize(" flow-1 ", " task-1 "); assertSame(expected, actual); ArgumentCaptor captor = ArgumentCaptor.forClass(DmsWorkflowPrintFilesGrantForm.class); verify(dmsResourceApi).grantWorkflowPrintFiles(eq("jnpf-flowable"), captor.capture()); assertEquals("user-1", captor.getValue().getUserId()); assertEquals(2, captor.getValue().getFiles().size()); for (DmsPersonalFolderFileForm.FileRelation relation : captor.getValue().getFiles()) { assertNull(relation.getValidTo()); } } /** 验证不存在流程申请时不会调用授权接口。 */ @Test void rejectsAuthorizationWhenRequestDoesNotExist() { when(requestMapper.selectList(any())).thenReturn(List.of()); DataException exception = assertThrows(DataException.class, () -> service.authorize("flow-1", "task-1")); assertTrue(exception.getMessage().contains("未找到记录打印申请")); verify(dmsResourceApi, never()).grantWorkflowPrintFiles(any(), any()); } /** * 验证流水查询由 A、B 表实体组装指定的四个返回字段。 */ @Test void findsUnissuedRecordBySerialNumber() throws Exception { DmsJiluDayinLiushuiEntity record = new DmsJiluDayinLiushuiEntity(); record.setId("record-1"); record.setLiushuihao("LS001"); record.setDayinZixiangId("item-1"); DmsJiluDayinShenqingZixiangEntity item = new DmsJiluDayinShenqingZixiangEntity(); item.setWenjianMingcheng("检验记录"); item.setBanbenhao("V2"); when(mapper.selectOne(any())).thenReturn(record); when(itemMapper.selectOne(any())).thenReturn(item); DmsRecordPrintSerialVO result = service.findBySerialNumber(" LS001 ", ""); assertEquals("LS001", result.getLiushuihao()); assertEquals("record-1", result.getId()); assertEquals("检验记录", result.getWenjianMingcheng()); assertEquals("V2", result.getBanbenhao()); } /** * 验证发放人有值时拒绝条码重复签收或发放。 */ @Test void rejectsSerialNumberWithIssuer() { DmsJiluDayinLiushuiEntity record = new DmsJiluDayinLiushuiEntity(); record.setFafangren("user-1"); when(mapper.selectOne(any())).thenReturn(record); DataException exception = assertThrows(DataException.class, () -> service.findBySerialNumber("LS001", "")); assertEquals("该条码已签收或发放请勿重复操作", exception.getMessage()); verify(itemMapper, never()).selectOne(any()); } /** * 验证批量发放使用条件更新写入双方信息和同一个操作时间。 */ @Test void issuesEveryRecordWithOneOperationTime() throws Exception { DmsJiluDayinLiushuiEntity first = issueRecord("record-1", "LS001", null); DmsJiluDayinLiushuiEntity second = issueRecord("record-2", "LS002", ""); DmsJiluDayinShenqingZixiangEntity printItem = new DmsJiluDayinShenqingZixiangEntity(); printItem.setDayinFenshu("5"); printItem.setYiqianfaShuliang("1"); when(mapper.selectList(any())).thenReturn(java.util.Arrays.asList(first, second)); when(mapper.update(isNull(), any())).thenReturn(1); when(mapper.selectPrintItemForUpdate("item-1")).thenReturn(printItem); when(itemMapper.update(any(DmsJiluDayinShenqingZixiangEntity.class), any())) .thenReturn(1); service.issue(issueForm(issueItem("LS001", "issuer-1", "dept-1", "receiver-1", "dept-2"), issueItem("LS002", "issuer-2", "dept-3", "receiver-2", "dept-4"))); ArgumentCaptor> captor = ArgumentCaptor.forClass(LambdaUpdateWrapper.class); verify(mapper, times(2)).update(isNull(), captor.capture()); Date operationTime = null; for (LambdaUpdateWrapper update : captor.getAllValues()) { String sqlSet = update.getSqlSet(); assertTrue(sqlSet.contains("fafangren")); assertTrue(sqlSet.contains("fafang_bumen")); assertTrue(sqlSet.contains("jieshouren")); assertTrue(sqlSet.contains("jieshou_bumen")); assertTrue(sqlSet.contains("fafang_shijian")); assertTrue(sqlSet.contains("jieshou_shijian")); assertTrue(update.getSqlSegment().contains("f_delete_mark")); assertTrue(update.getSqlSegment().contains("fafangren")); for (Object value : update.getParamNameValuePairs().values()) { if (value instanceof Date) { if (operationTime == null) { operationTime = (Date) value; } else { assertSame(operationTime, value); } } } } assertNotNull(operationTime); ArgumentCaptor updatedItem = ArgumentCaptor.forClass(DmsJiluDayinShenqingZixiangEntity.class); verify(itemMapper).update(updatedItem.capture(), any()); assertEquals("3", updatedItem.getValue().getYiqianfaShuliang()); assertEquals("2", updatedItem.getValue().getWeiqianfaShuliang()); verify(mapper).selectPrintItemForUpdate("item-1"); } @Test void rejectsIssueWhenPrintItemIsMissing() { when(mapper.selectList(any())).thenReturn(java.util.List.of( issueRecord("record-1", "LS001", null))); when(mapper.update(isNull(), any())).thenReturn(1); assertThrows(DataException.class, () -> service.issue(issueForm( issueItem("LS001", "issuer-1", "dept-1", "receiver-1", "dept-2")))); verify(itemMapper, never()).update(any(DmsJiluDayinShenqingZixiangEntity.class), any()); } @Test void updatesIssueCountsForEachPrintItem() { DmsJiluDayinLiushuiEntity first = issueRecord("record-1", "LS001", null); DmsJiluDayinLiushuiEntity second = issueRecord("record-2", "LS002", null); second.setDayinZixiangId("item-2"); DmsJiluDayinShenqingZixiangEntity firstItem = new DmsJiluDayinShenqingZixiangEntity(); firstItem.setDayinFenshu("3"); DmsJiluDayinShenqingZixiangEntity secondItem = new DmsJiluDayinShenqingZixiangEntity(); secondItem.setDayinFenshu("4"); secondItem.setYiqianfaShuliang("2"); when(mapper.selectList(any())).thenReturn(java.util.List.of(first, second)); when(mapper.update(isNull(), any())).thenReturn(1); when(mapper.selectPrintItemForUpdate("item-1")).thenReturn(firstItem); when(mapper.selectPrintItemForUpdate("item-2")).thenReturn(secondItem); when(itemMapper.update(any(DmsJiluDayinShenqingZixiangEntity.class), any())) .thenReturn(1); service.issue(issueForm(issueItem("LS001", "issuer-1", "dept-1", "receiver-1", "dept-2"), issueItem("LS002", "issuer-2", "dept-3", "receiver-2", "dept-4"))); ArgumentCaptor updatedItems = ArgumentCaptor.forClass(DmsJiluDayinShenqingZixiangEntity.class); verify(itemMapper, times(2)).update(updatedItems.capture(), any()); assertEquals("1", updatedItems.getAllValues().get(0).getYiqianfaShuliang()); assertEquals("2", updatedItems.getAllValues().get(0).getWeiqianfaShuliang()); assertEquals("3", updatedItems.getAllValues().get(1).getYiqianfaShuliang()); assertEquals("1", updatedItems.getAllValues().get(1).getWeiqianfaShuliang()); } @Test void accumulatesRecoveredCountsByPrintItem() { DmsJiluDayinLiushuiEntity first = issueRecord("record-1", "LS001", null); DmsJiluDayinLiushuiEntity second = issueRecord("record-2", "LS002", null); DmsJiluDayinLiushuiEntity third = issueRecord("record-3", "LS003", null); third.setDayinZixiangId("item-2"); DmsJiluDayinShenqingZixiangEntity firstItem = new DmsJiluDayinShenqingZixiangEntity(); firstItem.setYihuishouShuliang("1"); DmsJiluDayinShenqingZixiangEntity secondItem = new DmsJiluDayinShenqingZixiangEntity(); when(mapper.selectList(any())).thenReturn(java.util.List.of(first, second, third)); when(mapper.update(isNull(), any())).thenReturn(1); when(mapper.selectPrintItemForUpdate("item-1")).thenReturn(firstItem); when(mapper.selectPrintItemForUpdate("item-2")).thenReturn(secondItem); when(itemMapper.update(any(DmsJiluDayinShenqingZixiangEntity.class), any())) .thenReturn(1); service.huishou(huishouForm("LS001", "LS002", "LS003")); ArgumentCaptor updatedItems = ArgumentCaptor.forClass(DmsJiluDayinShenqingZixiangEntity.class); verify(itemMapper, times(2)).update(updatedItems.capture(), any()); assertEquals("3", updatedItems.getAllValues().get(0).getYihuishouShuliang()); assertEquals("1", updatedItems.getAllValues().get(1).getYihuishouShuliang()); verify(mapper, times(3)).update(isNull(), any()); } @Test void rejectsRecoveryWhenPrintItemIsMissing() { when(mapper.selectList(any())).thenReturn(java.util.List.of( issueRecord("record-1", "LS001", null))); when(mapper.update(isNull(), any())).thenReturn(1); assertThrows(DataException.class, () -> service.huishou(huishouForm("LS001"))); verify(itemMapper, never()).update(any(DmsJiluDayinShenqingZixiangEntity.class), any()); } /** * 验证任一流水已经发放时整批拒绝更新。 */ @Test void rejectsIssueBatchContainingIssuedRecord() { when(mapper.selectList(any())).thenReturn(java.util.Arrays.asList( issueRecord("record-1", "LS001", "issuer-0"))); DataException exception = assertThrows(DataException.class, () -> service.issue(issueForm( issueItem("LS001", "issuer-1", "dept-1", "receiver-1", "dept-2")))); assertEquals("该条码已签收或发放请勿重复操作", exception.getMessage()); verify(mapper, never()).update(isNull(), any()); } /** * 验证发放方法声明成功和失败审计动作。 */ @Test void issueMethodDeclaresAuditLog() throws Exception { AuditLog auditLog = DmsRecordPrintServiceImpl.class .getMethod("issue", DmsRecordPrintIssueForm.class) .getAnnotation(AuditLog.class); assertNotNull(auditLog); assertEquals("FAFANG", auditLog.action()); assertEquals("FAFANG_FAIL", auditLog.failureAction()); assertEquals("dms_jilu_dayin_liushui", auditLog.targetTable()); } @Test void confirmMethodDoesNotAddPrintAudit() throws Exception { AuditLog auditLog = DmsRecordPrintServiceImpl.class .getMethod("confirm", String.class) .getAnnotation(AuditLog.class); // 打印确认不额外记录正式审计,保留实际流水与业务状态。 assertNull(auditLog); } /** * 验证成册预览按份数预占流水,但不更新 A、B 表。 */ @Test void preparesBoundCopiesWithoutPersistingPrintRecords() throws Exception { DmsJiluDayinShenqingZixiangEntity item = item("chengce", "2", null); prepareSuccessfulReservation(item, "JL001", "JL002"); DmsRecordPrintPrepareVO result = service.prepare("item-1"); assertEquals(2, result.getSerialCount()); assertEquals(2, result.getCopies().size()); assertEquals("JL001", result.getCopies().get(0).getSerialNo()); assertEquals("JL002", result.getCopies().get(1).getSerialNo()); assertNull(result.getCopies().get(0).getPageNo()); assertNull(result.getCopies().get(0).getRecordId()); verify(pageCountService, never()).getPageCount(any()); assertReservedMetadata(item, 2); } /** * 验证分散打印的流水号数量等于去重页数乘以打印份数。 */ @Test void preparesLoosePageCopiesByPageCountTimesPrintCount() throws Exception { DmsJiluDayinShenqingZixiangEntity item = item("fensan", "2", "3,1,3"); UUID fileCenterVersionId = UUID.fromString("00000000-0000-0000-0000-000000000002"); DmsWenjianBanbenEntity banben = new DmsWenjianBanbenEntity(); banben.setWenjianZhongxinWenjianId("00000000-0000-0000-0000-000000000001"); banben.setWenjianZhongxinBanbenId(fileCenterVersionId.toString()); DmsFilePageCountVO pageCount = new DmsFilePageCountVO(); pageCount.setPageCount(4); when(banbenMapper.selectById("tenant-1", "business-version-1")).thenReturn(banben); when(pageCountService.getPageCount(fileCenterVersionId)).thenReturn(pageCount); prepareSuccessfulReservation(item, "JL001", "JL002", "JL003", "JL004"); DmsRecordPrintPrepareVO result = service.prepare("item-1"); assertEquals(4, result.getSerialCount()); assertEquals(java.util.Arrays.asList(1, 3), result.getSelectedPages()); assertEquals(1, result.getCopies().get(0).getCopyIndex()); assertEquals(1, result.getCopies().get(0).getPageNo()); assertEquals(3, result.getCopies().get(1).getPageNo()); assertEquals(2, result.getCopies().get(2).getCopyIndex()); verify(pageCountService).getPageCount(fileCenterVersionId); assertReservedMetadata(item, 4); } /** * 验证重复打开预览时复用原预占,不再次消耗流水号。 */ @Test void reusesExistingReservationWithoutTakingNewSerialNumbers() throws Exception { DmsJiluDayinShenqingZixiangEntity item = item("chengce", "1", null); DmsRecordPrintReservation reservation = reservation(item, "JL001"); UserInfo user = new UserInfo(); user.setUserId("user-1"); when(identity.requireUser()).thenReturn(user); when(identity.tenantId(user)).thenReturn("tenant-1"); when(mapper.selectPrintItemForUpdate("item-1")).thenReturn(item); when(mapper.countActivePrintRecords("item-1")).thenReturn(0); when(reservationStore.findByPrintItem("tenant-1", "item-1")) .thenReturn(reservation); DmsRecordPrintPrepareVO result = service.prepare("item-1"); assertEquals("reservation-1", result.getReservationId()); assertEquals("JL001", result.getCopies().get(0).getSerialNo()); verify(mapper, never()).lockSerialAllocation(); verify(billRuleApi, never()).getBillNumber(any()); verify(reservationStore, never()).create(any(), anyLong()); } /** * 验证点击打印确认后才写入 A 表并更新 B 表。 */ @Test void confirmsReservedSerialNumbersAndPersistsPrintMetadata() throws Exception { DmsJiluDayinShenqingZixiangEntity item = item("chengce", "2", null); DmsRecordPrintReservation reservation = reservation( item, "JL001", "JL002"); UserInfo user = new UserInfo(); user.setUserId("user-1"); when(identity.requireUser()).thenReturn(user); when(identity.tenantId(user)).thenReturn("tenant-1"); when(reservationStore.findById("tenant-1", "reservation-1")) .thenReturn(reservation); when(mapper.selectPrintItemForUpdate("item-1")).thenReturn(item); when(mapper.selectList(any())).thenReturn(java.util.Collections.emptyList()); when(mapper.countActivePrintRecords("item-1")).thenReturn(0); when(mapper.insertPrintRecords(any())).thenReturn(2); when(mapper.markPrintItemProcessing(any())).thenReturn(1); DmsRecordPrintConfirmVO result = service.confirm("reservation-1"); assertEquals(Boolean.TRUE, result.getConfirmed()); assertEquals(2, result.getCopies().size()); assertEquals("JL001", result.getCopies().get(0).getSerialNo()); assertNotNull(result.getCopies().get(0).getRecordId()); assertPersistedMetadata(item, 2); verify(reservationStore).markConfirmed(any(DmsRecordPrintReservation.class), anyLong()); } /** * 验证已确认预占的网络重试直接返回缓存结果,不重复写库。 */ @Test void returnsConfirmedReservationIdempotently() throws Exception { DmsJiluDayinShenqingZixiangEntity item = item("chengce", "1", null); DmsRecordPrintReservation reservation = reservation(item, "JL001"); reservation.setStatus(DmsRecordPrintReservation.STATUS_CONFIRMED); reservation.setRecordIds(java.util.Collections.singletonList("record-1")); UserInfo user = new UserInfo(); user.setUserId("user-1"); when(identity.requireUser()).thenReturn(user); when(identity.tenantId(user)).thenReturn("tenant-1"); when(reservationStore.findById("tenant-1", "reservation-1")) .thenReturn(reservation); DmsRecordPrintConfirmVO result = service.confirm("reservation-1"); assertEquals("record-1", result.getCopies().get(0).getRecordId()); verify(mapper, never()).selectPrintItemForUpdate(any()); verify(mapper, never()).insertPrintRecords(any()); } /** * 验证已经存在 A 表记录时,在取号之前拒绝重复打印。 */ @Test void rejectsRepeatedPrintBeforeTakingSerialNumber() { DmsJiluDayinShenqingZixiangEntity item = item("chengce", "1", null); when(mapper.selectPrintItemForUpdate("item-1")).thenReturn(item); when(mapper.countActivePrintRecords("item-1")).thenReturn(1); DataException exception = assertThrows(DataException.class, () -> service.prepare("item-1")); assertEquals("该记录已经打印,不允许重复打印", exception.getMessage()); verify(mapper, never()).lockSerialAllocation(); verify(billRuleApi, never()).getBillNumber(any()); } /** * 配置一次成功打印需要的 Mapper 和流水号返回值。 */ private void prepareSuccessfulReservation( DmsJiluDayinShenqingZixiangEntity item, String... serialNumbers) throws Exception { UserInfo user = new UserInfo(); user.setUserId("user-1"); when(identity.requireUser()).thenReturn(user); when(identity.tenantId(user)).thenReturn("tenant-1"); when(mapper.selectPrintItemForUpdate("item-1")).thenReturn(item); when(mapper.countActivePrintRecords("item-1")).thenReturn(0); when(mapper.lockSerialAllocation()).thenReturn(1); ActionResult[] results = new ActionResult[serialNumbers.length]; for (int index = 0; index < serialNumbers.length; index++) { results[index] = ActionResult.success("取号成功", serialNumbers[index]); } when(billRuleApi.getBillNumber("jiluDayinLiushuihao")) .thenReturn(results[0], java.util.Arrays.copyOfRange(results, 1, results.length)); } /** * 断言预览只保存 Redis 预占,不写 A、B 表。 */ private void assertReservedMetadata( DmsJiluDayinShenqingZixiangEntity item, int expectedRecords) { ArgumentCaptor captor = ArgumentCaptor.forClass(DmsRecordPrintReservation.class); verify(reservationStore).create(captor.capture(), anyLong()); DmsRecordPrintReservation reservation = captor.getValue(); assertEquals(expectedRecords, reservation.getSerialNumbers().size()); assertEquals("user-1", reservation.getUserId()); assertEquals("tenant-1", reservation.getTenantId()); assertEquals("item-1", reservation.getPrintItemId()); assertEquals(DmsRecordPrintReservation.STATUS_PENDING, reservation.getStatus()); verify(mapper, never()).insertPrintRecords(any()); verify(mapper, never()).markPrintItemProcessing(any()); assertNull(item.getDayinren()); assertNull(item.getDayinShijian()); assertEquals("daiqianfa", item.getDayinZhuangtai()); } /** * 断言确认阶段写入的所有 A 表记录与 B 表使用同一打印元数据。 */ private void assertPersistedMetadata( DmsJiluDayinShenqingZixiangEntity item, int expectedRecords) { ArgumentCaptor> captor = ArgumentCaptor.forClass(List.class); verify(mapper).insertPrintRecords(captor.capture()); List records = captor.getValue(); assertEquals(expectedRecords, records.size()); Date printTime = records.get(0).getDayinShijian(); for (DmsJiluDayinLiushuiEntity record : records) { assertEquals("user-1", record.getDayinren()); assertSame(printTime, record.getDayinShijian()); assertEquals("item-1", record.getDayinZixiangId()); assertEquals("print-1", record.getDayinId()); } assertEquals("user-1", item.getDayinren()); assertSame(printTime, item.getDayinShijian()); assertEquals("dayinzhong", item.getDayinZhuangtai()); } private DmsRecordPrintReservation reservation( DmsJiluDayinShenqingZixiangEntity item, String... serialNumbers) { DmsRecordPrintReservation reservation = new DmsRecordPrintReservation(); reservation.setReservationId("reservation-1"); reservation.setTenantId("tenant-1"); reservation.setUserId("user-1"); reservation.setPrintItemId(item.getId()); reservation.setItemVersion(item.getVersion()); reservation.setPrintType(item.getDayinLeixing()); reservation.setPrintCount(Integer.valueOf(item.getDayinFenshu())); reservation.setSelectedPages(java.util.Collections.emptyList()); reservation.setSerialNumbers(java.util.Arrays.asList(serialNumbers)); reservation.setStatus(DmsRecordPrintReservation.STATUS_PENDING); reservation.setCreatedAt(System.currentTimeMillis()); reservation.setExpiresAt(System.currentTimeMillis() + 60000L); return reservation; } /** * 构造可打印的 B 表实体。 */ private DmsJiluDayinShenqingZixiangEntity item( String printType, String printCount, String pages) { DmsJiluDayinShenqingZixiangEntity item = new DmsJiluDayinShenqingZixiangEntity(); item.setId("item-1"); item.setForeignId("print-1"); item.setBanbenId("business-version-1"); item.setDayinLeixing(printType); item.setDayinFenshu(printCount); item.setYema(pages); item.setYidayinFenshu("0"); item.setDayinZhuangtai("daiqianfa"); return item; } /** 构造已映射文件中心文件和版本的业务版本实体。 */ private DmsWenjianBanbenEntity businessVersion(String id) { DmsWenjianBanbenEntity version = new DmsWenjianBanbenEntity(); version.setId(id); version.setWenjianZhongxinWenjianId(UUID.randomUUID().toString()); version.setWenjianZhongxinBanbenId(UUID.randomUUID().toString()); return version; } /** * 构造打印流水实体。 */ private DmsJiluDayinLiushuiEntity issueRecord( String id, String serialNumber, String issuer) { DmsJiluDayinLiushuiEntity record = new DmsJiluDayinLiushuiEntity(); record.setId(id); record.setLiushuihao(serialNumber); record.setFafangren(issuer); record.setDayinZixiangId("item-1"); return record; } /** * 构造批量发放请求。 */ private DmsRecordPrintIssueForm issueForm(DmsRecordPrintIssueItemForm... items) { DmsRecordPrintIssueForm form = new DmsRecordPrintIssueForm(); form.setData(java.util.Arrays.asList(items)); return form; } private DmsRecordPrintHuishouForm huishouForm(String... serialNumbers) { DmsRecordPrintHuishouForm form = new DmsRecordPrintHuishouForm(); java.util.List items = new java.util.ArrayList<>(); for (String serialNumber : serialNumbers) { DmsRecordPrintHuishouItemForm item = new DmsRecordPrintHuishouItemForm(); item.setLiushuihao(serialNumber); item.setGuihuanren("returner"); item.setGuihuanBumen("return-dept"); item.setHuishouren("receiver"); item.setHuishouBumen("receive-dept"); items.add(item); } form.setData(items); return form; } /** * 构造单条发放明细。 */ private DmsRecordPrintIssueItemForm issueItem( String serialNumber, String issuer, String issuerDepartment, String receiver, String receiverDepartment) { DmsRecordPrintIssueItemForm item = new DmsRecordPrintIssueItemForm(); item.setLiushuihao(serialNumber); item.setFafangren(issuer); item.setFafangBumen(issuerDepartment); item.setJieshouren(receiver); item.setJieshouBumen(receiverDepartment); return item; } }