| | |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchGenerateReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.MesWmItemReceiptPageReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.MesWmItemReceiptSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.detail.MesWmItemReceiptDetailSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDetailDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptLineDO; |
| | | 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.itemreceipt.MesWmItemReceiptMapper; |
| | | import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; |
| | | import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmItemReceiptStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; |
| | |
| | | import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; |
| | | import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; |
| | | import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; |
| | | import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.ErpPurchaseOrderApi; |
| | | import cn.iocoder.yudao.module.srm.api.supplier.SrmSupplierApi; |
| | | import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi; |
| | | import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO; |
| | | import org.springframework.security.core.Authentication; |
| | | import org.springframework.security.core.context.SecurityContextHolder; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.context.annotation.Lazy; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.flowable.engine.repository.ProcessDefinition; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | import java.util.Arrays; |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; |
| | | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| | | import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; |
| | | |
| | | /** |
| | |
| | | @Validated |
| | | @Slf4j |
| | | public class MesWmItemReceiptServiceImpl implements MesWmItemReceiptService { |
| | | |
| | | private static final String ITEM_RECEIPT_APPROVE_CATEGORY_CODE = "item_receipt_approve"; |
| | | |
| | | @Resource |
| | | private MesWmItemReceiptMapper itemReceiptMapper; |
| | |
| | | |
| | | @Resource |
| | | private BpmProcessInstanceApi processInstanceApi; |
| | | @Resource |
| | | private BpmProcessDefinitionService bpmProcessDefinitionService; |
| | | |
| | | @Resource |
| | | private ErpPurchaseOrderApi purchaseOrderApi; |
| | | |
| | | @Resource |
| | | private MdmItemApi mdmItemApi; |
| | | |
| | | @Resource |
| | | private MesWmWarehouseService warehouseService; |
| | | @Resource |
| | | private MesWmWarehouseLocationService warehouseLocationService; |
| | | @Resource |
| | | private MesWmWarehouseAreaService warehouseAreaService; |
| | | @Resource |
| | | private MesWmBatchService batchService; |
| | | |
| | | @Override |
| | | public Long createItemReceipt(MesWmItemReceiptSaveReqVO createReqVO) { |
| | |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @Deprecated |
| | | public void finishItemReceipt(Long id) { |
| | | // 1. 校验存在 |
| | | MesWmItemReceiptDO receipt = validateItemReceiptExists(id); |
| | |
| | | throw exception(WM_ITEM_RECEIPT_STATUS_ERROR); |
| | | } |
| | | |
| | | // 2. 遍历所有明细,创建库存事务(增加库存 + 记录流水) |
| | | // 2. 完成入库(库存事务 + 状态 + 到货通知 + 采购订单回写) |
| | | completeItemReceipt(receipt); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void confirmItemReceipt(Long id, Long warehouseId, Long locationId, Long areaId) { |
| | | // 1. 校验单据存在 |
| | | MesWmItemReceiptDO receipt = validateItemReceiptExists(id); |
| | | // 2. 校验状态:草稿、旧流程的待上架(且不在 BPM 审批中)、待执行入库 均允许确认 |
| | | validateItemReceiptConfirmable(receipt); |
| | | // 3. 校验行 |
| | | List<MesWmItemReceiptLineDO> lines = itemReceiptLineService.getItemReceiptLineListByReceiptId(id); |
| | | if (CollUtil.isEmpty(lines)) { |
| | | throw exception(WM_ITEM_RECEIPT_NO_LINE); |
| | | } |
| | | // 4. 校验入库位置(仓库 / 库区 / 库位)的层级关系 |
| | | validateConfirmLocation(receipt.getCode(), warehouseId, locationId, areaId); |
| | | // 5. 逐行校验入库数量,并为启用批次管理但还没批次的物料补齐批次 |
| | | Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap( |
| | | convertList(lines, MesWmItemReceiptLineDO::getItemId)); |
| | | for (MesWmItemReceiptLineDO line : lines) { |
| | | validateConfirmLineQuantity(receipt.getCode(), line, itemMap); |
| | | fillLineBatch(receipt, line, itemMap); |
| | | } |
| | | // 6. 补齐上架明细:没有明细的行按“行入库数量 + 所选位置”生成一条;已有明细的保持原样 |
| | | createDetailsForConfirm(receipt, lines, warehouseId, locationId, areaId); |
| | | |
| | | // 7. 完成入库(库存事务 + 状态 + 到货通知 + 采购订单回写) |
| | | completeItemReceipt(receipt); |
| | | } |
| | | |
| | | /** |
| | | * 完成入库:创建库存事务、更新单据与关联单据状态 |
| | | */ |
| | | private void completeItemReceipt(MesWmItemReceiptDO receipt) { |
| | | // 1. 遍历所有明细,创建库存事务(增加库存 + 记录流水) |
| | | createTransactionList(receipt); |
| | | |
| | | // 3. 更新入库单状态 |
| | | // 2. 更新入库单状态 |
| | | itemReceiptMapper.updateById(new MesWmItemReceiptDO() |
| | | .setId(id).setStatus(MesWmItemReceiptStatusEnum.FINISHED.getStatus())); |
| | | .setId(receipt.getId()).setStatus(MesWmItemReceiptStatusEnum.FINISHED.getStatus())); |
| | | |
| | | // 4. 更新关联的到货通知单状态 |
| | | // 3. 更新关联的到货通知单状态 |
| | | if (receipt.getNoticeId() != null) { |
| | | arrivalNoticeService.finishArrivalNotice(receipt.getNoticeId()); |
| | | } |
| | | |
| | | // 5. 回写 ERP 采购订单的入库数量 |
| | | // 4. 回写 ERP 采购订单的入库数量 |
| | | updateErpPurchaseOrderInCount(receipt); |
| | | } |
| | | |
| | | /** |
| | | * 校验采购入库单是否允许确认入库 |
| | | * |
| | | * 草稿(新流程)、旧流程的待上架(无 BPM 审批)、待执行入库(旧流程已上架)都允许; |
| | | * 审批中的单据必须等审批结束,已完成/已取消的不允许。 |
| | | */ |
| | | private void validateItemReceiptConfirmable(MesWmItemReceiptDO receipt) { |
| | | MesWmItemReceiptStatusEnum status = Arrays.stream(MesWmItemReceiptStatusEnum.values()) |
| | | .filter(item -> ObjUtil.equal(item.getStatus(), receipt.getStatus())) |
| | | .findFirst().orElse(null); |
| | | String statusName = status != null ? status.getName() : String.valueOf(receipt.getStatus()); |
| | | |
| | | // 1. BPM 审批中的单据不允许直接入库,否则会绕过审批 |
| | | if (ObjUtil.equal(MesWmItemReceiptStatusEnum.APPROVING.getStatus(), receipt.getStatus()) |
| | | && StrUtil.isNotBlank(receipt.getProcessInstanceId())) { |
| | | throw new ServiceException(WM_ITEM_RECEIPT_CONFIRM_STATUS_ERROR.getCode(), |
| | | "采购入库单[" + receipt.getCode() + "]正在审批中(当前状态:" + statusName + "),不能确认入库。" |
| | | + "请等待审批通过后再确认入库;若审批已驳回,请按审批意见修改后重新提交。"); |
| | | } |
| | | // 2. 已完成 / 已取消不允许重复确认 |
| | | if (ObjUtil.equal(MesWmItemReceiptStatusEnum.FINISHED.getStatus(), receipt.getStatus()) |
| | | || ObjUtil.equal(MesWmItemReceiptStatusEnum.CANCELED.getStatus(), receipt.getStatus())) { |
| | | throw new ServiceException(WM_ITEM_RECEIPT_CONFIRM_STATUS_ERROR.getCode(), |
| | | "采购入库单[" + receipt.getCode() + "]当前状态为[" + statusName + "],不能确认入库。" |
| | | + "只有草稿、待上架或待执行入库的单据可以确认入库,请刷新列表确认单据状态。"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 校验确认入库时选择的仓库 / 库区 / 库位 |
| | | */ |
| | | private void validateConfirmLocation(String receiptCode, Long warehouseId, Long locationId, Long areaId) { |
| | | if (warehouseId == null || locationId == null || areaId == null) { |
| | | throw new ServiceException(WM_ITEM_RECEIPT_CONFIRM_LOCATION_REQUIRED.getCode(), |
| | | "采购入库单[" + receiptCode + "]确认入库前必须选择入库仓库、库区和库位(当前" |
| | | + "仓库=" + (warehouseId != null ? warehouseId : "未选择") |
| | | + ",库区=" + (locationId != null ? locationId : "未选择") |
| | | + ",库位=" + (areaId != null ? areaId : "未选择") |
| | | + ")。请点击「确认入库」,在弹窗中依次选择仓库、库区、库位后重新提交。"); |
| | | } |
| | | MesWmWarehouseDO warehouse = warehouseService.getWarehouse(warehouseId); |
| | | if (warehouse == null) { |
| | | throw new ServiceException(WM_ITEM_RECEIPT_CONFIRM_LOCATION_REQUIRED.getCode(), |
| | | "所选入库仓库(ID=" + warehouseId + ")不存在或已被删除,无法确认入库。" |
| | | + "请刷新页面后重新选择仓库、库区、库位。"); |
| | | } |
| | | MesWmWarehouseLocationDO location = warehouseLocationService.getWarehouseLocation(locationId); |
| | | if (location == null) { |
| | | throw new ServiceException(WM_ITEM_RECEIPT_CONFIRM_LOCATION_REQUIRED.getCode(), |
| | | "所选入库库区(ID=" + locationId + ")不存在或已被删除,无法确认入库。" |
| | | + "请刷新页面后重新选择仓库、库区、库位。"); |
| | | } |
| | | MesWmWarehouseAreaDO area = warehouseAreaService.getWarehouseArea(areaId); |
| | | if (area == null) { |
| | | throw new ServiceException(WM_ITEM_RECEIPT_CONFIRM_LOCATION_REQUIRED.getCode(), |
| | | "所选入库库位(ID=" + areaId + ")不存在或已被删除,无法确认入库。" |
| | | + "请刷新页面后重新选择仓库、库区、库位。"); |
| | | } |
| | | // 仓库 → 库区 → 库位 的层级必须一致 |
| | | if (ObjUtil.notEqual(location.getWarehouseId(), warehouse.getId())) { |
| | | MesWmWarehouseDO locationWarehouse = warehouseService.getWarehouse(location.getWarehouseId()); |
| | | throw new ServiceException(WM_ITEM_RECEIPT_CONFIRM_LOCATION_MISMATCH.getCode(), |
| | | "入库仓库与库区不匹配:所选仓库[" + warehouse.getName() + "],库区[" + location.getName() |
| | | + "]属于仓库[" + (locationWarehouse != null ? locationWarehouse.getName() |
| | | : "ID=" + location.getWarehouseId()) + "]。请重新选择同一仓库下的库区。"); |
| | | } |
| | | if (ObjUtil.notEqual(area.getLocationId(), location.getId())) { |
| | | MesWmWarehouseLocationDO areaLocation = warehouseLocationService.getWarehouseLocation(area.getLocationId()); |
| | | throw new ServiceException(WM_ITEM_RECEIPT_CONFIRM_LOCATION_MISMATCH.getCode(), |
| | | "入库库区与库位不匹配:所选库区[" + location.getName() + "],库位[" + area.getName() |
| | | + "]属于库区[" + (areaLocation != null ? areaLocation.getName() |
| | | : "ID=" + area.getLocationId()) + "]。请重新选择同一库区下的库位。"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 校验单行入库数量 |
| | | */ |
| | | private void validateConfirmLineQuantity(String receiptCode, MesWmItemReceiptLineDO line, |
| | | Map<Long, MdmItemRespDTO> itemMap) { |
| | | if (line.getReceivedQuantity() != null && line.getReceivedQuantity().compareTo(BigDecimal.ZERO) > 0) { |
| | | return; |
| | | } |
| | | MdmItemRespDTO item = itemMap.get(line.getItemId()); |
| | | String itemText = item != null ? item.getCode() + " " + item.getName() : "ID=" + line.getItemId(); |
| | | throw new ServiceException(WM_ITEM_RECEIPT_CONFIRM_QUANTITY_INVALID.getCode(), |
| | | "采购入库单[" + receiptCode + "]的物料行[" + itemText + "]入库数量为[" |
| | | + (line.getReceivedQuantity() != null ? line.getReceivedQuantity().toPlainString() : "空") |
| | | + "],必须大于 0 才能入库。请编辑该物料行,核对并填写实际收货数量后重试。"); |
| | | } |
| | | |
| | | /** |
| | | * 为启用批次管理但还没有批次的物料行补齐批次 |
| | | * |
| | | * 由到货通知单生成的入库行不会预先生成批次,这里在确认入库时统一生成, |
| | | * 避免库管逐行打开物料行保存一次。 |
| | | */ |
| | | private void fillLineBatch(MesWmItemReceiptDO receipt, MesWmItemReceiptLineDO line, |
| | | Map<Long, MdmItemRespDTO> itemMap) { |
| | | MdmItemRespDTO item = itemMap.get(line.getItemId()); |
| | | if (item == null || !Boolean.TRUE.equals(item.getIsBatchManaged()) || line.getBatchId() != null) { |
| | | return; |
| | | } |
| | | MesWmBatchGenerateReqVO batchReqVO = new MesWmBatchGenerateReqVO(); |
| | | batchReqVO.setItemId(line.getItemId()).setProduceDate(line.getProductionDate()) |
| | | .setExpireDate(line.getExpireDate()).setLotNumber(line.getLotNumber()) |
| | | .setVendorId(receipt.getVendorId()).setReceiptDate(receipt.getReceiptDate()) |
| | | .setPurchaseOrderCode(receipt.getPurchaseOrderCode()); |
| | | MesWmBatchDO batch; |
| | | try { |
| | | batch = batchService.getOrGenerateBatchCode(batchReqVO); |
| | | } catch (ServiceException ex) { |
| | | // 批次配置要求的字段(生产日期、有效期、生产批号等)没有填:把行上下文补进提示 |
| | | throw new ServiceException(WM_ITEM_RECEIPT_CONFIRM_BATCH_GENERATE_FAILED.getCode(), |
| | | "物料[" + item.getCode() + " " + item.getName() + "]生成批次失败:" + ex.getMessage() |
| | | + "。请编辑采购入库单里该物料的物料行,补充批次要求的字段(生产日期、有效期、生产批号)后重试。"); |
| | | } |
| | | if (batch == null) { |
| | | return; |
| | | } |
| | | line.setBatchId(batch.getId()).setBatchCode(batch.getCode()); |
| | | itemReceiptLineService.updateItemReceiptLineBatch(line.getId(), batch.getId(), batch.getCode()); |
| | | } |
| | | |
| | | /** |
| | | * 确认入库时补齐上架明细:没有明细的行按行入库数量生成一条明细,已有明细的校验数量合计 |
| | | */ |
| | | private void createDetailsForConfirm(MesWmItemReceiptDO receipt, List<MesWmItemReceiptLineDO> lines, |
| | | Long warehouseId, Long locationId, Long areaId) { |
| | | for (MesWmItemReceiptLineDO line : lines) { |
| | | List<MesWmItemReceiptDetailDO> details = itemReceiptDetailService |
| | | .getItemReceiptDetailListByLineId(line.getId()); |
| | | if (CollUtil.isEmpty(details)) { |
| | | // 旧流程“待执行入库”的单据应当已经有上架明细,缺了说明数据不完整 |
| | | if (ObjUtil.equal(MesWmItemReceiptStatusEnum.APPROVED.getStatus(), receipt.getStatus())) { |
| | | throw new ServiceException(WM_ITEM_RECEIPT_CONFIRM_DETAIL_MISSING.getCode(), |
| | | "采购入库单[" + receipt.getCode() + "]处于旧流程的「待执行入库」状态,但物料行(ID=" |
| | | + line.getId() + ")没有上架明细,无法确认入库。" |
| | | + "请将该单据取消后重新生成,或联系管理员补齐上架明细。"); |
| | | } |
| | | MesWmItemReceiptDetailSaveReqVO detailReqVO = new MesWmItemReceiptDetailSaveReqVO(); |
| | | detailReqVO.setReceiptId(receipt.getId()).setLineId(line.getId()) |
| | | .setItemId(line.getItemId()).setQuantity(line.getReceivedQuantity()) |
| | | .setBatchId(line.getBatchId()) |
| | | .setWarehouseId(warehouseId).setLocationId(locationId).setAreaId(areaId); |
| | | itemReceiptDetailService.createItemReceiptDetail(detailReqVO); |
| | | continue; |
| | | } |
| | | // 已有上架明细(旧流程):数量合计必须与行入库数量一致 |
| | | BigDecimal totalDetailQty = CollectionUtils.getSumValue(details, |
| | | MesWmItemReceiptDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO); |
| | | if (line.getReceivedQuantity() == null || totalDetailQty.compareTo(line.getReceivedQuantity()) != 0) { |
| | | MdmItemRespDTO item = mdmItemApi.getItem(line.getItemId()).getCheckedData(); |
| | | String itemText = item != null ? item.getCode() + " " + item.getName() : "ID=" + line.getItemId(); |
| | | throw new ServiceException(WM_ITEM_RECEIPT_DETAIL_QUANTITY_MISMATCH.getCode(), |
| | | "采购入库单[" + receipt.getCode() + "]的物料行[" + itemText + "]上架明细数量合计为[" |
| | | + totalDetailQty.toPlainString() + "],与行入库数量[" |
| | | + (line.getReceivedQuantity() != null ? line.getReceivedQuantity().toPlainString() : "空") |
| | | + "]不一致,无法确认入库。请在物料行上核对入库数量,或取消该单据后按简化流程重新生成。"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | // 6. 遍历行创建入库单行 |
| | | for (MesWmArrivalNoticeLineDO noticeLine : lines) { |
| | | BigDecimal receivable = noticeLine.getQualifiedQuantity() != null |
| | | ? noticeLine.getQualifiedQuantity() : noticeLine.getArrivalQuantity(); |
| | | // 整行已退供应商时不生成零数量入库行;其余行仍正常收货。 |
| | | if (receivable == null || receivable.signum() <= 0) { |
| | | continue; |
| | | } |
| | | MesWmItemReceiptLineDO receiptLine = new MesWmItemReceiptLineDO(); |
| | | receiptLine.setReceiptId(receipt.getId()); |
| | | receiptLine.setArrivalNoticeLineId(noticeLine.getId()); |
| | | receiptLine.setPurchaseOrderItemId(noticeLine.getPurchaseOrderItemId()); |
| | | receiptLine.setItemId(noticeLine.getItemId()); |
| | | // 使用合格数量(如果有 IQC 则是合格数量,否则是到货数量) |
| | | receiptLine.setReceivedQuantity(noticeLine.getQualifiedQuantity() != null ? noticeLine.getQualifiedQuantity() : noticeLine.getArrivalQuantity()); |
| | | receiptLine.setReceivedQuantity(receivable); |
| | | // 按采购订单行单价快照金额,供来票/对账使用 |
| | | fillReceiptLinePrice(receiptLine); |
| | | itemReceiptLineService.createItemReceiptLineFromArrivalNoticeLine(receiptLine); |
| | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void submitItemReceiptApproval(Long id, String processDefinitionKey) { |
| | | // 1. 校验存在 + 草稿状态 |
| | | validateItemReceiptExistsAndDraft(id); |
| | | MesWmItemReceiptDO receipt = validateItemReceiptExistsAndDraft(id); |
| | | // 审批入口与普通提交入口保持一致,空行单据不能进入审批。 |
| | | List<MesWmItemReceiptLineDO> lines = itemReceiptLineService.getItemReceiptLineListByReceiptId(id); |
| | | if (CollUtil.isEmpty(lines)) { |
| | | throw exception(WM_ITEM_RECEIPT_NO_LINE); |
| | | } |
| | | |
| | | // 2. 创建 BPM 流程实例 |
| | | Long userId = getCurrentUserId(); |
| | |
| | | return; |
| | | } |
| | | |
| | | if (StrUtil.isBlank(processDefinitionKey)) { |
| | | throw exception(WM_ITEM_RECEIPT_BPM_PROCESS_DEFINITION_NOT_EXISTS); |
| | | } |
| | | ProcessDefinition processDefinition = bpmProcessDefinitionService.getActiveProcessDefinition(processDefinitionKey); |
| | | if (processDefinition == null || bpmProcessDefinitionService |
| | | .getProcessDefinitionInfoListByCategory(ITEM_RECEIPT_APPROVE_CATEGORY_CODE).stream() |
| | | .noneMatch(info -> Objects.equals(info.getProcessDefinitionId(), processDefinition.getId()))) { |
| | | throw exception(WM_ITEM_RECEIPT_BPM_PROCESS_DEFINITION_NOT_EXISTS); |
| | | } |
| | | |
| | | String processInstanceId = processInstanceApi.createProcessInstance(userId, |
| | | new BpmProcessInstanceCreateReqDTO() |
| | | .setProcessDefinitionKey(processDefinitionKey) |
| | | .setBusinessKey(String.valueOf(id))); |
| | | .setBusinessKey(String.valueOf(id)) |
| | | .setVariables(Map.of("businessNo", receipt.getCode()))); |
| | | |
| | | // 3. 更新入库单状态为审批中 |
| | | itemReceiptMapper.updateById(new MesWmItemReceiptDO() |
| | |
| | | // 2. 根据审批结果更新状态 |
| | | Integer newStatus = convertBpmResultToReceiptStatus(bpmResult); |
| | | if (newStatus != null) { |
| | | itemReceiptMapper.updateById(new MesWmItemReceiptDO() |
| | | .setId(id).setStatus(newStatus)); |
| | | itemReceiptMapper.update(null, new LambdaUpdateWrapper<MesWmItemReceiptDO>() |
| | | .eq(MesWmItemReceiptDO::getId, id) |
| | | .set(MesWmItemReceiptDO::getStatus, newStatus) |
| | | .set(MesWmItemReceiptDO::getApproveTime, |
| | | BpmTaskStatusEnum.APPROVE.getStatus().equals(bpmResult) ? LocalDateTime.now() : null)); |
| | | } |
| | | } |
| | | |
| | |
| | | * 获取当前用户 ID |
| | | */ |
| | | private Long getCurrentUserId() { |
| | | Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); |
| | | if (authentication != null && authentication.getPrincipal() instanceof Long) { |
| | | return (Long) authentication.getPrincipal(); |
| | | } |
| | | return 1L; // 默认用户 |
| | | return Objects.requireNonNull(getLoginUserId(), "采购入库审批需要登录用户"); |
| | | } |
| | | |
| | | /** |