| | |
| | | import cn.hutool.core.collection.ListUtil; |
| | | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| | | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderProcessDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDetailDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceLineDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.wm.productproduce.MesWmProductProduceLineMapper; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.wm.productproduce.MesWmProductProduceMapper; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductProduceStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProcessService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProductService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderProcessService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.productreceipt.MesWmProductReceiptService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; |
| | |
| | | @MockitoBean |
| | | private MesWmProductProduceDetailService productProduceDetailService; |
| | | @MockitoBean |
| | | private MesWmProductProduceLineMapper produceLineMapper; |
| | | @MockitoBean |
| | | private MesProWorkOrderService workOrderService; |
| | | @MockitoBean |
| | | private MesProWorkOrderProcessService workOrderProcessService; |
| | | @MockitoBean |
| | | private MesProRouteProductService routeProductService; |
| | | @MockitoBean |
| | | private MesProRouteProcessService routeProcessService; |
| | | @MockitoBean |
| | | private MesWmProductReceiptService productReceiptService; |
| | | @MockitoBean |
| | | private MesMdItemService itemService; |
| | | @MockitoBean |
| | | private MesWmBatchService batchService; |
| | | @MockitoBean |
| | |
| | | when(warehouseService.getWarehouseByCode(MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE)).thenReturn(wh); |
| | | when(locationService.getWarehouseLocationByCode(MesWmWarehouseLocationDO.WIP_VIRTUAL_LOCATION)).thenReturn(loc); |
| | | when(areaService.getWarehouseAreaByCode(MesWmWarehouseAreaDO.WIP_VIRTUAL_AREA)).thenReturn(area); |
| | | mockNotLastProcess(); |
| | | MesMdItemDO item = new MesMdItemDO(); |
| | | item.setId(itemId); |
| | | item.setMdmItemId(itemId); |
| | | when(itemService.validateItemExists(any())).thenReturn(item); |
| | | |
| | | // mock: 通过 sourceLineId 直接定位 PENDING 产出行 |
| | | MesWmProductProduceLineDO pendingLine = MesWmProductProduceLineDO.builder() |
| | |
| | | .batchId(batchId).batchCode(batchCode) |
| | | .qualityStatus(MesWmQualityStatusEnum.PENDING.getStatus()) |
| | | .build(); |
| | | when(productProduceLineService.validateProductProduceLineExists(sourceLineId)) |
| | | .thenReturn(pendingLine); |
| | | when(produceLineMapper.selectByIdForUpdate(sourceLineId)).thenReturn(pendingLine); |
| | | |
| | | // mock: finishProductProduce 内部查行和明细(用于创建库存事务) |
| | | MesWmProductProduceLineDO qualifiedLine = MesWmProductProduceLineDO.builder() |
| | |
| | | |
| | | // mock: finishProductProduce 中按行查明细 |
| | | MesWmProductProduceDetailDO qualifiedDetail = MesWmProductProduceDetailDO.builder() |
| | | .lineId(100L).quantity(BigDecimal.valueOf(80)).build(); |
| | | .lineId(100L).quantity(BigDecimal.valueOf(80)).warehouseId(whId).build(); |
| | | MesWmProductProduceDetailDO unqualifiedDetail = MesWmProductProduceDetailDO.builder() |
| | | .lineId(101L).quantity(BigDecimal.valueOf(20)).build(); |
| | | .lineId(101L).quantity(BigDecimal.valueOf(20)).warehouseId(whId).build(); |
| | | when(productProduceDetailService.getProductProduceDetailListByLineId(100L)) |
| | | .thenReturn(ListUtil.of(qualifiedDetail)); |
| | | when(productProduceDetailService.getProductProduceDetailListByLineId(101L)) |
| | |
| | | MesWmProductProduceDO updatedProduce = productProduceMapper.selectById(produce.getId()); |
| | | assertEquals(MesWmProductProduceStatusEnum.FINISHED.getStatus(), updatedProduce.getStatus()); |
| | | |
| | | // 断言 5:创建了库存事务 |
| | | verify(wmTransactionService, times(2)).createTransaction(any()); |
| | | // 断言 5:只为合格品行创建库存事务(不合格品不计入可用库存) |
| | | verify(wmTransactionService, times(1)).createTransaction(any()); |
| | | } |
| | | |
| | | @Test |
| | |
| | | when(warehouseService.getWarehouseByCode(any())).thenReturn(wh); |
| | | when(locationService.getWarehouseLocationByCode(any())).thenReturn(loc); |
| | | when(areaService.getWarehouseAreaByCode(any())).thenReturn(area); |
| | | mockNotLastProcess(); |
| | | |
| | | // mock: 通过 sourceLineId 直接定位 PENDING 产出行 |
| | | MesWmProductProduceLineDO pendingLine = MesWmProductProduceLineDO.builder() |
| | |
| | | .itemId(itemId).quantity(BigDecimal.valueOf(50)) |
| | | .qualityStatus(MesWmQualityStatusEnum.PENDING.getStatus()) |
| | | .build(); |
| | | when(productProduceLineService.validateProductProduceLineExists(sourceLineId)) |
| | | .thenReturn(pendingLine); |
| | | when(produceLineMapper.selectByIdForUpdate(sourceLineId)).thenReturn(pendingLine); |
| | | |
| | | // mock: finishProductProduce 查行和明细 |
| | | MesWmProductProduceLineDO qualifiedLine = MesWmProductProduceLineDO.builder() |
| | |
| | | when(locationService.getWarehouseLocationByCode(any())).thenReturn(loc); |
| | | when(areaService.getWarehouseAreaByCode(any())).thenReturn(area); |
| | | |
| | | // mock: validateProductProduceLineExists 抛异常 |
| | | when(productProduceLineService.validateProductProduceLineExists(sourceLineId)) |
| | | .thenThrow(new ServiceException(WM_PRODUCT_PRODUCE_LINE_NOT_EXISTS)); |
| | | // mock: 产出行不存在 |
| | | when(produceLineMapper.selectByIdForUpdate(sourceLineId)).thenReturn(null); |
| | | |
| | | // 调用,应该抛异常 |
| | | ServiceException ex = assertThrows(ServiceException.class, () -> |
| | |
| | | assertEquals(WM_PRODUCT_PRODUCE_LINE_NOT_EXISTS.getCode(), ex.getCode()); |
| | | } |
| | | |
| | | /** 末道工序返回非当前工序,避免测试走到确切末道工序的仓库校验分支 */ |
| | | private void mockNotLastProcess() { |
| | | MesProWorkOrderProcessDO lastProcess = new MesProWorkOrderProcessDO(); |
| | | lastProcess.setProcessId(-1L); |
| | | when(workOrderProcessService.getLastWorkOrderProcessByWorkOrderId(any())).thenReturn(lastProcess); |
| | | } |
| | | |
| | | } |