| | |
| | | private MesProFeedbackMapper feedbackMapper; |
| | | |
| | | @MockitoBean |
| | | private MesProFeedbackEquipmentService equipmentService; |
| | | |
| | | @MockitoBean |
| | | private MesProWorkOrderService workOrderService; |
| | | @MockitoBean |
| | | private MesProRouteProcessService routeProcessService; |
| | |
| | | private MdmItemBatchConfigApi itemBatchConfigApi; |
| | | @MockitoBean |
| | | private BpmProcessInstanceApi processInstanceApi; |
| | | |
| | | @Test |
| | | public void testEquipmentSnapshotSurvivesStatusUpdates() { |
| | | MesProFeedbackDO feedback = randomPojo(MesProFeedbackDO.class, f -> f.setMachineryIds("10,20")); |
| | | feedbackMapper.insert(feedback); |
| | | feedbackMapper.updateById(new MesProFeedbackDO().setId(feedback.getId()) |
| | | .setStatus(MesProFeedbackStatusEnum.APPROVING.getStatus())); |
| | | assertEquals("10,20", feedbackMapper.selectById(feedback.getId()).getMachineryIds()); |
| | | } |
| | | |
| | | @Test |
| | | public void testUpdateProFeedbackWhenIpqcFinish_success_withUnqualified() { |
| | |
| | | assertEquals(0, materialScrapQty.compareTo(updatedFeedback.getMaterialScrapQuantity())); |
| | | assertEquals(0, otherScrapQty.compareTo(updatedFeedback.getOtherScrapQuantity())); |
| | | |
| | | // 断言 4:更新了任务和工单的已生产数量 |
| | | // 注意:数量经过 DB 存取后 scale 可能变化,用 any() 匹配 |
| | | verify(taskService).updateProducedQuantity(eq(taskId), |
| | | any(BigDecimal.class), any(BigDecimal.class), any(BigDecimal.class)); |
| | | verify(workOrderService).updateProducedQuantity(eq(workOrderId), |
| | | any(BigDecimal.class)); |
| | | // 产量已经在报工审批时累计,质检回调不能重复累计。 |
| | | verify(taskService).updateQualityQuantity(taskId, qualifiedQty, unqualifiedQty); |
| | | verify(taskService, never()).updateProducedQuantity(anyLong(), any(), any(), any()); |
| | | verify(workOrderService, never()).updateProducedQuantity(anyLong(), any()); |
| | | } |
| | | |
| | | @Test |
| | |
| | | when(routeProcessService.getRouteProcessByRouteIdAndProcessId(routeId, processId)) |
| | | .thenReturn(routeProcess); |
| | | |
| | | // mock: 产品产出单 |
| | | MesWmProductProduceDO produce = randomPojo(MesWmProductProduceDO.class); |
| | | when(productProduceService.generateProductProduce(any(), eq(false), any())).thenReturn(produce); |
| | | |
| | | // mock: 产出行(用于 updateTaskAndWorkOrderByFeedback) |
| | | MesWmProductProduceLineDO qualifiedLine = MesWmProductProduceLineDO.builder() |
| | | .quantity(BigDecimal.valueOf(80)) |
| | | .qualityStatus(MesWmQualityStatusEnum.PASS.getStatus()).build(); |
| | | when(produceLineService.getProductProduceLineListByFeedbackId(feedback.getId())) |
| | | .thenReturn(ListUtil.of(qualifiedLine)); |
| | | // 关键末道工序累计工单产量,质量数量等待检验。 |
| | | when(workOrderProcessService.getLastWorkOrderProcessByWorkOrderId(feedback.getWorkOrderId())) |
| | | .thenReturn(new MesProWorkOrderProcessDO().setProcessId(processId)); |
| | | |
| | | // 调用 |
| | | MesProFeedbackApproveReqVO reqVO = new MesProFeedbackApproveReqVO(); |
| | | reqVO.setId(feedback.getId()); |
| | | boolean result = feedbackService.approveFeedback(reqVO); |
| | | |
| | | // 断言 1:返回 true(已完成) |
| | | assertTrue(result); |
| | | assertFalse(result); |
| | | |
| | | // 断言 2:状态为已完成,uncheckQuantity 清零 |
| | | // 未经检验的报工不允许直接入库。 |
| | | MesProFeedbackDO updated = feedbackMapper.selectById(feedback.getId()); |
| | | assertEquals(MesProFeedbackStatusEnum.FINISHED.getStatus(), updated.getStatus()); |
| | | assertEquals(0, BigDecimal.ZERO.compareTo(updated.getUncheckQuantity())); |
| | | assertEquals(MesProFeedbackStatusEnum.UNCHECK.getStatus(), updated.getStatus()); |
| | | assertEquals(0, feedback.getFeedbackQuantity().compareTo(updated.getUncheckQuantity())); |
| | | assertEquals(0, BigDecimal.ZERO.compareTo(updated.getQualifiedQuantity())); |
| | | |
| | | // 断言 3:调用了产出单生成 + 入库 + 任务/工单更新 |
| | | verify(productProduceService).generateProductProduce(any(), eq(false), any()); |
| | | verify(productProduceService).finishProductProduce(produce.getId()); |
| | | verify(productProduceService).generateProductProduce(any(), eq(true), any()); |
| | | verify(productProduceService, never()).finishProductProduce(anyLong()); |
| | | verify(taskService).updateProducedQuantity(eq(feedback.getTaskId()), |
| | | any(BigDecimal.class), any(BigDecimal.class), any(BigDecimal.class)); |
| | | verify(workOrderService).updateProducedQuantity(eq(feedback.getWorkOrderId()), |
| | |
| | | verify(productProduceService).generateProductProduce(any(), eq(true), any()); |
| | | verify(productProduceService, never()).finishProductProduce(anyLong()); |
| | | |
| | | // 断言 4:没有更新任务/工单数量(等 IPQC 回调) |
| | | verify(taskService, never()).updateProducedQuantity(anyLong(), any(), any(), any()); |
| | | // 产量在审批时累计,产出仍保持待检;非末道不更新工单总产量。 |
| | | verify(taskService).updateProducedQuantity(eq(feedback.getTaskId()), any(), any(), any()); |
| | | verify(workOrderService, never()).updateProducedQuantity(anyLong(), any()); |
| | | } |
| | | |
| | |
| | | reqVO.setId(feedback.getId()); |
| | | boolean result = feedbackService.approveFeedback(reqVO); |
| | | |
| | | // 断言 1:返回 true(已完成) |
| | | assertTrue(result); |
| | | assertFalse(result); |
| | | |
| | | // 断言 2:状态为已完成 |
| | | MesProFeedbackDO updated = feedbackMapper.selectById(feedback.getId()); |
| | | assertEquals(MesProFeedbackStatusEnum.FINISHED.getStatus(), updated.getStatus()); |
| | | assertEquals(MesProFeedbackStatusEnum.UNCHECK.getStatus(), updated.getStatus()); |
| | | |
| | | // 断言 3:不生成产出单,不更新任务/工单 |
| | | verify(productProduceService, never()).generateProductProduce(any(), anyBoolean(), any()); |
| | | verify(taskService, never()).updateProducedQuantity(anyLong(), any(), any(), any()); |
| | | // 非关键工序也生成产出并累计任务进度,但不累计工单总产量。 |
| | | verify(productProduceService).generateProductProduce(any(), eq(true), any()); |
| | | verify(productProduceService, never()).finishProductProduce(anyLong()); |
| | | verify(taskService).updateProducedQuantity(eq(feedback.getTaskId()), any(), any(), any()); |
| | | verify(workOrderService, never()).updateProducedQuantity(anyLong(), any()); |
| | | } |
| | | |
| | | @Test |
| | |
| | | when(routeProcessService.getRouteProcessByRouteIdAndProcessId(routeId, processId)) |
| | | .thenReturn(routeProcess); |
| | | |
| | | // 调用,应该抛异常 |
| | | // 待检数量不再阻止非检验标识工序报工。 |
| | | MesProFeedbackApproveReqVO reqVO = new MesProFeedbackApproveReqVO(); |
| | | reqVO.setId(feedback.getId()); |
| | | assertThrows(Exception.class, () -> |
| | | feedbackService.approveFeedback(reqVO)); |
| | | |
| | | // 断言:不应该执行任何后续操作 |
| | | verify(productProduceService, never()).generateProductProduce(any(), anyBoolean(), any()); |
| | | verify(itemConsumeService, never()).generateItemConsume(any()); |
| | | assertFalse(feedbackService.approveFeedback(reqVO)); |
| | | verify(productProduceService).generateProductProduce(any(), eq(true), any()); |
| | | verify(productProduceService, never()).finishProductProduce(anyLong()); |
| | | } |
| | | |
| | | @Test |
| | | public void testApproveFeedback_nonKeyCheck_directFinishAndCleanUncheck() { |
| | | public void testApproveFeedback_nonKeyCheck_enterUncheckAndCleanQuantity() { |
| | | // 准备数据:非关键 + 质检工序(!key+check),uncheckQuantity > 0 |
| | | // 应放行(checkFlag=true 不拦截 uncheckQuantity),直接完结并清零 uncheckQuantity |
| | | // 应放行并进入待检验,审批阶段只累计一次任务产量。 |
| | | Long routeId = randomLongId(); |
| | | Long processId = randomLongId(); |
| | | MesProFeedbackDO feedback = randomPojo(MesProFeedbackDO.class, o -> { |
| | |
| | | reqVO.setId(feedback.getId()); |
| | | boolean result = feedbackService.approveFeedback(reqVO); |
| | | |
| | | // 断言 1:返回 true(直接完成,不走 UNCHECK) |
| | | assertTrue(result); |
| | | assertFalse(result); |
| | | |
| | | // 断言 2:状态为已完成,uncheckQuantity 被清零 |
| | | // 质检工序无论是否关键工序,都进入待检验。 |
| | | MesProFeedbackDO updated = feedbackMapper.selectById(feedback.getId()); |
| | | assertEquals(MesProFeedbackStatusEnum.FINISHED.getStatus(), updated.getStatus()); |
| | | assertEquals(0, BigDecimal.ZERO.compareTo(updated.getUncheckQuantity())); |
| | | assertEquals(MesProFeedbackStatusEnum.UNCHECK.getStatus(), updated.getStatus()); |
| | | assertEquals(0, feedback.getFeedbackQuantity().compareTo(updated.getUncheckQuantity())); |
| | | |
| | | // 断言 3:非关键工序不生成产出单 |
| | | verify(productProduceService, never()).generateProductProduce(any(), anyBoolean(), any()); |
| | | verify(productProduceService).generateProductProduce(any(), eq(true), any()); |
| | | verify(productProduceService, never()).finishProductProduce(anyLong()); |
| | | verify(taskService).updateProducedQuantity(eq(feedback.getTaskId()), any(), any(), any()); |
| | | verify(workOrderService, never()).updateProducedQuantity(anyLong(), any()); |
| | | } |
| | | |
| | | // ==================== 顺序报工(上一道工序完成后才能报下一道)测试 ==================== |
| | |
| | | MesProFeedbackQuickCreateReqVO req = new MesProFeedbackQuickCreateReqVO(); |
| | | req.setTaskId(curTaskId); |
| | | req.setFeedbackQuantity(BigDecimal.TEN); |
| | | req.setFeedbackTime(java.time.LocalDateTime.of(2026, 10, 20, 9, 30)); |
| | | MesProFeedbackQuickCreateRespVO resp = feedbackService.quickCreateFeedback(req); |
| | | assertNotNull(resp); |
| | | assertNotNull(resp.getFeedbackId()); |
| | | assertEquals(req.getFeedbackTime(), feedbackMapper.selectById(resp.getFeedbackId()).getFeedbackTime()); |
| | | verify(autoCodeRecordService).generateAutoCode(anyString()); |
| | | } |
| | | |