| | |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.MesWmProductReceiptImportRespVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.MesWmProductReceiptPageReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.MesWmProductReceiptSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.detail.MesWmProductReceiptDetailSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Long generateProductReceipt(MesWmProductProduceDO produce, |
| | | List<MesWmProductProduceLineDO> produceLines) { |
| | | List<MesWmProductProduceLineDO> produceLines, |
| | | boolean lastProcess) { |
| | | List<MesWmProductProduceLineDO> qualifiedLines = produceLines.stream() |
| | | .filter(line -> ObjUtil.equal(line.getQualityStatus(), MesWmQualityStatusEnum.PASS.getStatus())) |
| | | .filter(line -> line.getQuantity() != null && line.getQuantity().compareTo(BigDecimal.ZERO) > 0) |
| | |
| | | |
| | | MesWmProductReceiptDO receipt = MesWmProductReceiptDO.builder() |
| | | .code(code) |
| | | .name("生产完成自动入库-" + workOrderCode) |
| | | .name((lastProcess ? "生产完成自动入库-" : "工序产出自动入库-") + workOrderCode) |
| | | .workOrderId(produce.getWorkOrderId()) |
| | | .produceId(produce.getId()) |
| | | .itemId(firstMdmItemId) |
| | | .receiptDate(LocalDateTime.now()) |
| | | .status(MesWmProductReceiptStatusEnum.PREPARE.getStatus()) |
| | | .remark("末道工序产出自动生成,产出单ID:" + produce.getId()) |
| | | .remark((lastProcess ? "末道工序产出自动生成,产出单ID:" : "中间工序产出自动生成(半成品),产出单ID:") |
| | | + produce.getId()) |
| | | .build(); |
| | | productReceiptMapper.insert(receipt); |
| | | |
| | | MesWmWarehouseDO virtualWarehouse = warehouseService.getWarehouseByCode( |
| | | MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE); |
| | | MesWmWarehouseLocationDO virtualLocation = locationService.getWarehouseLocationByCode( |
| | | MesWmWarehouseLocationDO.WIP_VIRTUAL_LOCATION); |
| | | MesWmWarehouseAreaDO virtualArea = areaService.getWarehouseAreaByCode( |
| | | MesWmWarehouseAreaDO.WIP_VIRTUAL_AREA); |
| | | |
| | | for (MesWmProductProduceLineDO produceLine : qualifiedLines) { |
| | | MesMdItemDO item = mdItemService.getItem(produceLine.getItemId()); |
| | |
| | | ? item.getMdmItemId() : produceLine.getItemId(); |
| | | List<cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDetailDO> details = |
| | | productProduceDetailService.getProductProduceDetailListByLineId(produceLine.getId()); |
| | | Long warehouseId = CollUtil.isNotEmpty(details) ? details.get(0).getWarehouseId() : virtualWarehouse.getId(); |
| | | Long locationId = CollUtil.isNotEmpty(details) ? details.get(0).getLocationId() : virtualLocation.getId(); |
| | | Long areaId = CollUtil.isNotEmpty(details) ? details.get(0).getAreaId() : virtualArea.getId(); |
| | | if (CollUtil.isEmpty(details)) throw exception(WM_PRODUCT_RECPT_NO_DETAIL); |
| | | Long warehouseId = details.get(0).getWarehouseId(); |
| | | Long locationId = details.get(0).getLocationId(); |
| | | Long areaId = details.get(0).getAreaId(); |
| | | MesWmMaterialStockDO stock = materialStockService.getMaterialStockByCompositeKey( |
| | | mdmItemId, warehouseId, locationId, areaId, |
| | | produceLine.getBatchId(), null); |
| | | productReceiptLineMapper.insert(MesWmProductReceiptLineDO.builder() |
| | | MesWmProductReceiptLineDO receiptLine = MesWmProductReceiptLineDO.builder() |
| | | .receiptId(receipt.getId()) |
| | | .itemId(mdmItemId) |
| | | .materialStockId(stock != null ? stock.getId() : null) |
| | | .quantity(produceLine.getQuantity()) |
| | | .batchId(produceLine.getBatchId()) |
| | | .batchCode(produceLine.getBatchCode()) |
| | | .remark("末道工序合格品自动生成") |
| | | .build()); |
| | | .remark(lastProcess ? "末道工序合格品自动生成" : "中间工序合格品自动生成") |
| | | .build(); |
| | | productReceiptLineMapper.insert(receiptLine); |
| | | for (var detail : details) { |
| | | MesWmProductReceiptDetailSaveReqVO detailReq = new MesWmProductReceiptDetailSaveReqVO(); |
| | | detailReq.setReceiptId(receipt.getId()); |
| | | detailReq.setLineId(receiptLine.getId()); |
| | | detailReq.setItemId(mdmItemId); |
| | | detailReq.setQuantity(detail.getQuantity()); |
| | | detailReq.setBatchId(detail.getBatchId()); |
| | | detailReq.setWarehouseId(detail.getWarehouseId()); |
| | | detailReq.setLocationId(detail.getLocationId()); |
| | | detailReq.setAreaId(detail.getAreaId()); |
| | | productReceiptDetailService.createProductReceiptDetail(detailReq); |
| | | } |
| | | } |
| | | return receipt.getId(); |
| | | } |
| | |
| | | throw exception(WM_PRODUCT_RECPT_NO_DETAIL); |
| | | } |
| | | |
| | | // 自动入库单来源产出单已按工艺路线仓库记账,此处仅完成业务单据,避免实际仓库重复入库。 |
| | | // 手工创建的产品入库单仍执行“虚拟线边库 OUT + 实际仓库 IN”。 |
| | | if (receipt.getProduceId() == null) { |
| | | createTransactionList(receipt, details); |
| | | } |
| | | // 执行入库时才登记实际仓库库存,保证“未上架不上账” |
| | | createTransactionList(receipt, details); |
| | | |
| | | // 更新收货单状态 |
| | | productReceiptMapper.updateById(new MesWmProductReceiptDO() |
| | |
| | | MesWmWarehouseLocationDO virtualLocation = locationService.getWarehouseLocationByCode(MesWmWarehouseLocationDO.WIP_VIRTUAL_LOCATION); |
| | | MesWmWarehouseAreaDO virtualArea = areaService.getWarehouseAreaByCode(MesWmWarehouseAreaDO.WIP_VIRTUAL_AREA); |
| | | |
| | | // 2. 遍历明细,每条明细产生 OUT(虚拟线边库扣减)+ IN(实际仓库增加) |
| | | // 2. 遍历明细登记库存事务 |
| | | for (MesWmProductReceiptDetailDO detail : details) { |
| | | // 2.1 先从虚拟线边库出库(库存减少) |
| | | // 2.1 自动入库单:产出单完成时已把虚拟线边库产出记账,这里只登记实际仓库入库 |
| | | if (receipt.getProduceId() != null) { |
| | | if (virtualWarehouse != null && ObjUtil.equal(detail.getWarehouseId(), virtualWarehouse.getId())) { |
| | | continue; |
| | | } |
| | | createInTransaction(receipt, detail, null); |
| | | continue; |
| | | } |
| | | // 2.2 手工入库单:虚拟线边库出库 + 实际仓库入库 |
| | | Long outTransactionId = wmTransactionService.createTransaction(new MesWmTransactionSaveReqDTO() |
| | | .setType(MesWmTransactionTypeEnum.OUT.getType()).setItemId(detail.getItemId()) |
| | | .setQuantity(detail.getQuantity().negate()) // 库存减少 |
| | |
| | | .setCheckFlag(false) // 线边库允许负库存 |
| | | .setBizType(MesBizTypeConstants.WM_PRODUCT_RECPT).setBizId(receipt.getId()) |
| | | .setBizCode(receipt.getCode()).setBizLineId(detail.getLineId())); |
| | | // 2.2 再入实际仓库(库存增加) |
| | | wmTransactionService.createTransaction(new MesWmTransactionSaveReqDTO() |
| | | .setType(MesWmTransactionTypeEnum.IN.getType()).setItemId(detail.getItemId()) |
| | | .setQuantity(detail.getQuantity()) // 库存增加 |
| | | .setBatchId(detail.getBatchId()) |
| | | .setWarehouseId(detail.getWarehouseId()).setLocationId(detail.getLocationId()).setAreaId(detail.getAreaId()) |
| | | .setBizType(MesBizTypeConstants.WM_PRODUCT_RECPT).setBizId(receipt.getId()) |
| | | .setBizCode(receipt.getCode()).setBizLineId(detail.getLineId()) |
| | | .setRelatedTransactionId(outTransactionId)); // 关联出库事务 |
| | | createInTransaction(receipt, detail, outTransactionId); |
| | | } |
| | | } |
| | | |
| | | private void createInTransaction(MesWmProductReceiptDO receipt, MesWmProductReceiptDetailDO detail, |
| | | Long relatedTransactionId) { |
| | | wmTransactionService.createTransaction(new MesWmTransactionSaveReqDTO() |
| | | .setType(MesWmTransactionTypeEnum.IN.getType()).setItemId(detail.getItemId()) |
| | | .setQuantity(detail.getQuantity()) // 库存增加 |
| | | .setBatchId(detail.getBatchId()) |
| | | .setWarehouseId(detail.getWarehouseId()).setLocationId(detail.getLocationId()).setAreaId(detail.getAreaId()) |
| | | .setBizType(MesBizTypeConstants.WM_PRODUCT_RECPT).setBizId(receipt.getId()) |
| | | .setBizCode(receipt.getCode()).setBizLineId(detail.getLineId()) |
| | | .setRelatedTransactionId(relatedTransactionId)); // 关联出库事务 |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void cancelProductReceipt(Long id) { |