package cn.iocoder.yudao.module.erp.service.purchase; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum; import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseRequestDO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseRequestItemDO; import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseOrderItemMapper; import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseOrderMapper; import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseRequestItemMapper; import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseRequestMapper; import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; import cn.iocoder.yudao.module.erp.enums.ErpPurchaseOrderInStatusEnum; import cn.iocoder.yudao.module.erp.enums.ErpPurchaseOrderStatusEnum; import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; import cn.iocoder.yudao.module.mes.api.arrivalnotice.MesArrivalNoticeApi; import cn.iocoder.yudao.module.system.api.approval.ApprovalConfigApi; import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.math.BigDecimal; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; /** * ERP 采购订单 Service 实现类 * * @author 超级管理员 */ @Service @Validated @Slf4j public class ErpPurchaseOrderServiceImpl implements ErpPurchaseOrderService { /** * 采购订单审批业务类型编码(对应 system_approval_config.biz_type) * * 注意:改造为轻量级状态机审批前,此处原为 "purchase_request_approve", * 与采购申请(ErpPurchaseRequestServiceImpl)的 BPM 分类编码完全相同, * 导致采购订单查询审批流程时会命中采购申请的流程定义,两者互相串用。 * 现更正为采购订单专属编码。 */ private static final String PURCHASE_ORDER_APPROVE_BIZ_TYPE = "erp_purchase_order_approve"; @Resource private ErpPurchaseOrderMapper purchaseOrderMapper; @Resource private ErpPurchaseOrderItemMapper purchaseOrderItemMapper; @Resource private ErpNoRedisDAO noRedisDAO; @Resource private ErpSupplierService supplierService; @Resource private ErpAccountService accountService; @Resource private ApprovalConfigApi approvalConfigApi; @Resource private AdminUserApi adminUserApi; @Resource @Lazy private MesArrivalNoticeApi arrivalNoticeApi; @Resource private ErpPurchaseRequestItemMapper purchaseRequestItemMapper; @Resource private ErpPurchaseRequestMapper purchaseRequestMapper; @Resource private StorageAttachmentApi storageAttachmentApi; @Override @Transactional(rollbackFor = Exception.class) public Long createPurchaseOrder(ErpPurchaseOrderSaveReqVO createReqVO) { // 1.1 校验订单项的有效性 List purchaseOrderItems = validatePurchaseOrderItems(createReqVO.getItems()); // 1.2 校验供应商 supplierService.validateSupplier(createReqVO.getSupplierId()); // 1.3 校验结算账户 if (createReqVO.getAccountId() != null) { accountService.validateAccount(createReqVO.getAccountId()); } // 1.4 生成订单号,并校验唯一性 String no = noRedisDAO.generate(ErpNoRedisDAO.PURCHASE_ORDER_NO_PREFIX); if (purchaseOrderMapper.selectByNo(no) != null) { throw exception(PURCHASE_ORDER_NO_EXISTS); } // 2.1 插入订单(采购订单创建后为【未提交】状态,需提交进入审批流程) ErpPurchaseOrderDO purchaseOrder = BeanUtils.toBean(createReqVO, ErpPurchaseOrderDO.class, in -> in .setNo(no).setStatus(ErpPurchaseOrderStatusEnum.DRAFT.getStatus()) .setInCount(BigDecimal.ZERO).setInStatus(ErpPurchaseOrderInStatusEnum.NOT_IN.getStatus())); calculateTotalPrice(purchaseOrder, purchaseOrderItems); purchaseOrderMapper.insert(purchaseOrder); // 2.2 插入订单项 purchaseOrderItems.forEach(o -> o.setOrderId(purchaseOrder.getId())); purchaseOrderItemMapper.insertBatch(purchaseOrderItems); // 2.3 绑定附件 storageAttachmentApi.bindAttachments("file", "erp_purchase_order", purchaseOrder.getId(), createReqVO.getBlobIds()); return purchaseOrder.getId(); } @Override @Transactional(rollbackFor = Exception.class) public void updatePurchaseOrder(ErpPurchaseOrderSaveReqVO updateReqVO) { // 1.1 校验存在 ErpPurchaseOrderDO purchaseOrder = validatePurchaseOrderExists(updateReqVO.getId()); // 已审核状态不允许修改 if (ErpPurchaseOrderStatusEnum.APPROVE.getStatus().equals(purchaseOrder.getStatus())) { throw exception(PURCHASE_ORDER_UPDATE_FAIL_APPROVE, purchaseOrder.getNo()); } // 审批中不允许修改:需先由审批人「审核不通过」退回,才能重新修改并提交 if (ErpPurchaseOrderStatusEnum.PROCESS.getStatus().equals(purchaseOrder.getStatus())) { throw exception(PURCHASE_ORDER_UPDATE_FAIL_PROCESS, purchaseOrder.getNo()); } // 1.2 校验供应商 supplierService.validateSupplier(updateReqVO.getSupplierId()); // 1.3 校验结算账户 if (updateReqVO.getAccountId() != null) { accountService.validateAccount(updateReqVO.getAccountId()); } // 1.4 校验订单项的有效性 List purchaseOrderItems = validatePurchaseOrderItems(updateReqVO.getItems()); // 2.1 更新订单 ErpPurchaseOrderDO updateObj = BeanUtils.toBean(updateReqVO, ErpPurchaseOrderDO.class); calculateTotalPrice(updateObj, purchaseOrderItems); purchaseOrderMapper.updateById(updateObj); // 2.2 更新订单项 updatePurchaseOrderItemList(updateReqVO.getId(), purchaseOrderItems); // 2.3 更新附件 storageAttachmentApi.updateAttachments("file", "erp_purchase_order", updateReqVO.getId(), updateReqVO.getBlobIds()); } private void calculateTotalPrice(ErpPurchaseOrderDO purchaseOrder, List purchaseOrderItems) { purchaseOrder.setTotalCount(getSumValue(purchaseOrderItems, ErpPurchaseOrderItemDO::getCount, BigDecimal::add)); purchaseOrder.setTotalProductPrice(getSumValue(purchaseOrderItems, ErpPurchaseOrderItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)); purchaseOrder.setTotalTaxPrice(getSumValue(purchaseOrderItems, ErpPurchaseOrderItemDO::getTaxPrice, BigDecimal::add, BigDecimal.ZERO)); purchaseOrder.setTotalPrice(purchaseOrder.getTotalProductPrice().add(purchaseOrder.getTotalTaxPrice())); // 计算优惠价格 if (purchaseOrder.getDiscountPercent() == null) { purchaseOrder.setDiscountPercent(BigDecimal.ZERO); } purchaseOrder.setDiscountPrice(MoneyUtils.priceMultiplyPercent(purchaseOrder.getTotalPrice(), purchaseOrder.getDiscountPercent())); purchaseOrder.setTotalPrice(purchaseOrder.getTotalPrice().subtract(purchaseOrder.getDiscountPrice())); } @Override @Transactional(rollbackFor = Exception.class) public void updatePurchaseOrderStatus(Long id, Integer status) { boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); // 1.1 校验存在 ErpPurchaseOrderDO purchaseOrder = validatePurchaseOrderExists(id); // 1.1.1 审核通过属于审批动作,必须由配置内的审批人执行(服务端强制,避免绕过审核按钮自助通过) if (approve) { approvalConfigApi.validateApprover(PURCHASE_ORDER_APPROVE_BIZ_TYPE, getLoginUserId()); } // 1.2 校验状态 if (purchaseOrder.getStatus().equals(status)) { throw exception(approve ? PURCHASE_ORDER_APPROVE_FAIL : PURCHASE_ORDER_PROCESS_FAIL); } // 1.3 存在采购入库单,无法反审核 BigDecimal inCount = purchaseOrder.getInCount(); if (!approve && inCount != null && inCount.compareTo(BigDecimal.ZERO) > 0) { throw exception(PURCHASE_ORDER_PROCESS_FAIL_EXISTS_IN); } // 1.4 存在采购退货单,无法反审核 BigDecimal returnCount = purchaseOrder.getReturnCount(); if (!approve && returnCount != null && returnCount.compareTo(BigDecimal.ZERO) > 0) { throw exception(PURCHASE_ORDER_PROCESS_FAIL_EXISTS_RETURN); } // 2. 更新状态 int updateCount = purchaseOrderMapper.updateByIdAndStatus(id, purchaseOrder.getStatus(), new ErpPurchaseOrderDO().setStatus(status)); if (updateCount == 0) { throw exception(approve ? PURCHASE_ORDER_APPROVE_FAIL : PURCHASE_ORDER_PROCESS_FAIL); } } @Override @Transactional(rollbackFor = Exception.class) public void submitPurchaseOrder(Long id) { // 1.1 校验存在 ErpPurchaseOrderDO purchaseOrder = validatePurchaseOrderExists(id); // 1.2 只有【未提交】或【审核不通过】才允许提交 if (!ErpPurchaseOrderStatusEnum.DRAFT.getStatus().equals(purchaseOrder.getStatus()) && !ErpPurchaseOrderStatusEnum.REJECT.getStatus().equals(purchaseOrder.getStatus())) { throw exception(PURCHASE_ORDER_SUBMIT_FAIL_NOT_ALLOWED); } // 1.3 必须配置订单项 List items = purchaseOrderItemMapper.selectListByOrderId(id); if (CollUtil.isEmpty(items)) { throw exception(PURCHASE_ORDER_SUBMIT_FAIL_ITEM_EMPTY); } // 2. 校验审批已开启且配置了有效审批人(未开启审批时不允许提交) approvalConfigApi.validateApprovalEnabledAndGetApprovers(PURCHASE_ORDER_APPROVE_BIZ_TYPE); // 3. 置为审批中,并清空上一轮审核信息,避免驳回原因残留 purchaseOrderMapper.submitAndResetAuditInfo(id, ErpPurchaseOrderStatusEnum.PROCESS.getStatus()); } @Override public Set getPurchaseOrderApproverUserIds() { return approvalConfigApi.getApproverUserIds(PURCHASE_ORDER_APPROVE_BIZ_TYPE); } @Override @Transactional(rollbackFor = Exception.class) public void auditPurchaseOrder(Long id, Boolean pass, String reviewRemark) { // 1.1 校验存在 + 审批中状态 ErpPurchaseOrderDO purchaseOrder = validatePurchaseOrderExists(id); if (!ErpPurchaseOrderStatusEnum.PROCESS.getStatus().equals(purchaseOrder.getStatus())) { throw exception(PURCHASE_ORDER_AUDIT_FAIL_NOT_PROCESS); } // 1.2 校验当前登录人是配置的审批人(或签:任一人审核即可) Long userId = getLoginUserId(); approvalConfigApi.validateApprover(PURCHASE_ORDER_APPROVE_BIZ_TYPE, userId); // 2. 审核不通过:必须填写驳回原因,单据退回后可编辑并重新提交 if (!Boolean.TRUE.equals(pass)) { if (StrUtil.isBlank(reviewRemark)) { throw exception(PURCHASE_ORDER_AUDIT_REJECT_REASON_REQUIRED); } purchaseOrderMapper.auditPurchaseOrder(id, ErpPurchaseOrderStatusEnum.REJECT.getStatus(), userId, getUserNickname(userId), reviewRemark); return; } // 3. 审核通过 purchaseOrderMapper.auditPurchaseOrder(id, ErpPurchaseOrderStatusEnum.APPROVE.getStatus(), userId, getUserNickname(userId), reviewRemark); } /** * 获取用户昵称,用于冗余存储审核人姓名 */ private String getUserNickname(Long userId) { if (userId == null) { return null; } AdminUserRespDTO user = adminUserApi.getUser(userId); return user == null ? null : user.getNickname(); } @Override @Transactional(rollbackFor = Exception.class) public void updatePurchaseOrderAuditStatus(Long id, Integer bpmResult) { // 1. 校验存在 ErpPurchaseOrderDO purchaseOrder = validatePurchaseOrderExists(id); if (!ErpPurchaseOrderStatusEnum.PROCESS.getStatus().equals(purchaseOrder.getStatus())) { log.warn("[updatePurchaseOrderAuditStatus] 采购订单({}) 不处于审批中状态", id); return; } // 2. 根据审批结果更新状态 Integer newStatus = convertBpmResultToAuditStatus(bpmResult); if (newStatus != null) { purchaseOrderMapper.updateById(new ErpPurchaseOrderDO() .setId(id).setStatus(newStatus)); } } /** * 转换 BPM 审批结果为审核状态 * * 已废弃:采购订单不再走 BPM 流程,本方法仅为历史代码保留,不再被调用。 */ @Deprecated private Integer convertBpmResultToAuditStatus(Integer bpmResult) { if (BpmTaskStatusEnum.APPROVE.getStatus().equals(bpmResult)) { return ErpPurchaseOrderStatusEnum.APPROVE.getStatus(); } else if (BpmTaskStatusEnum.REJECT.getStatus().equals(bpmResult)) { return ErpPurchaseOrderStatusEnum.REJECT.getStatus(); } else if (BpmTaskStatusEnum.CANCEL.getStatus().equals(bpmResult)) { return ErpPurchaseOrderStatusEnum.CANCEL.getStatus(); } return null; } private List validatePurchaseOrderItems(List list) { // 转化为 ErpPurchaseOrderItemDO 列表(产品验证已移除) return convertList(list, o -> BeanUtils.toBean(o, ErpPurchaseOrderItemDO.class, item -> { item.setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())); if (item.getTotalPrice() == null) { return; } if (item.getTaxPercent() != null) { item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent())); } })); } private void updatePurchaseOrderItemList(Long id, List newList) { // 第一步,对比新老数据,获得添加、修改、删除的列表 List oldList = purchaseOrderItemMapper.selectListByOrderId(id); List> diffList = diffList(oldList, newList, (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); // 第二步,批量添加、修改、删除 if (CollUtil.isNotEmpty(diffList.get(0))) { diffList.get(0).forEach(o -> o.setOrderId(id)); purchaseOrderItemMapper.insertBatch(diffList.get(0)); } if (CollUtil.isNotEmpty(diffList.get(1))) { purchaseOrderItemMapper.updateBatch(diffList.get(1)); } if (CollUtil.isNotEmpty(diffList.get(2))) { purchaseOrderItemMapper.deleteByIds(convertList(diffList.get(2), ErpPurchaseOrderItemDO::getId)); } } @Override public void updatePurchaseOrderInCount(Long id, Map inCountMap) { List orderItems = purchaseOrderItemMapper.selectListByOrderId(id); // 1. 更新每个采购订单项 orderItems.forEach(item -> { BigDecimal inCount = inCountMap.getOrDefault(item.getId(), BigDecimal.ZERO); if (item.getInCount().equals(inCount)) { return; } if (inCount.compareTo(item.getCount()) > 0) { throw exception(PURCHASE_ORDER_ITEM_IN_FAIL_PRODUCT_EXCEED, "产品ID:" + item.getProductId(), item.getCount()); } purchaseOrderItemMapper.updateById(new ErpPurchaseOrderItemDO().setId(item.getId()).setInCount(inCount)); }); // 2. 更新采购订单 BigDecimal totalInCount = getSumValue(inCountMap.values(), value -> value, BigDecimal::add, BigDecimal.ZERO); purchaseOrderMapper.updateById(new ErpPurchaseOrderDO().setId(id).setInCount(totalInCount)); } @Override public void updatePurchaseOrderReturnCount(Long orderId, Map returnCountMap) { List orderItems = purchaseOrderItemMapper.selectListByOrderId(orderId); // 1. 更新每个采购订单项 orderItems.forEach(item -> { BigDecimal returnCount = returnCountMap.getOrDefault(item.getId(), BigDecimal.ZERO); if (item.getReturnCount().equals(returnCount)) { return; } if (returnCount.compareTo(item.getInCount()) > 0) { throw exception(PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED, "产品ID:" + item.getProductId(), item.getInCount()); } purchaseOrderItemMapper.updateById(new ErpPurchaseOrderItemDO().setId(item.getId()).setReturnCount(returnCount)); }); // 2. 更新采购订单 BigDecimal totalReturnCount = getSumValue(returnCountMap.values(), value -> value, BigDecimal::add, BigDecimal.ZERO); purchaseOrderMapper.updateById(new ErpPurchaseOrderDO().setId(orderId).setReturnCount(totalReturnCount)); } @Override @Transactional(rollbackFor = Exception.class) public void deletePurchaseOrder(List ids) { // 1. 校验不处于已审批 List purchaseOrders = purchaseOrderMapper.selectByIds(ids); if (CollUtil.isEmpty(purchaseOrders)) { return; } purchaseOrders.forEach(purchaseOrder -> { if (ErpAuditStatus.APPROVE.getStatus().equals(purchaseOrder.getStatus())) { throw exception(PURCHASE_ORDER_DELETE_FAIL_APPROVE, purchaseOrder.getNo()); } }); // 2. 遍历删除 purchaseOrders.forEach(purchaseOrder -> { // 2.1 删除附件 storageAttachmentApi.deleteAttachmentsByRecord("erp_purchase_order", purchaseOrder.getId()); // 2.2 删除订单 purchaseOrderMapper.deleteById(purchaseOrder.getId()); // 2.3 删除订单项 purchaseOrderItemMapper.deleteByOrderId(purchaseOrder.getId()); }); } private ErpPurchaseOrderDO validatePurchaseOrderExists(Long id) { ErpPurchaseOrderDO purchaseOrder = purchaseOrderMapper.selectById(id); if (purchaseOrder == null) { throw exception(PURCHASE_ORDER_NOT_EXISTS); } return purchaseOrder; } @Override public ErpPurchaseOrderDO getPurchaseOrder(Long id) { return purchaseOrderMapper.selectById(id); } @Override public ErpPurchaseOrderDO validatePurchaseOrder(Long id) { ErpPurchaseOrderDO purchaseOrder = validatePurchaseOrderExists(id); if (ObjectUtil.notEqual(purchaseOrder.getStatus(), ErpAuditStatus.APPROVE.getStatus())) { throw exception(PURCHASE_ORDER_NOT_APPROVE); } return purchaseOrder; } @Override public PageResult getPurchaseOrderPage(ErpPurchaseOrderPageReqVO pageReqVO) { return purchaseOrderMapper.selectPage(pageReqVO); } // ==================== 订单项 ==================== @Override public List getPurchaseOrderItemListByOrderId(Long orderId) { return purchaseOrderItemMapper.selectListByOrderId(orderId); } @Override public List getPurchaseOrderItemListByOrderIds(Collection orderIds) { if (CollUtil.isEmpty(orderIds)) { return Collections.emptyList(); } return purchaseOrderItemMapper.selectListByOrderIds(orderIds); } @Override public List getPurchaseOrderListBySupplierIdAndStatus(Long supplierId, Integer status) { if (supplierId == null) { return Collections.emptyList(); } return purchaseOrderMapper.selectList(supplierId, status); } @Override public List getPurchaseOrderList(List ids) { if (CollUtil.isEmpty(ids)) { return Collections.emptyList(); } return purchaseOrderMapper.selectByIds(ids); } @Override public List getPurchaseOrderListBySource(Integer sourceType, Long sourceId) { if (sourceType == null || sourceId == null) { return Collections.emptyList(); } return purchaseOrderMapper.selectListBySource(sourceType, sourceId); } @Override public void updatePurchaseOrderInStatus(Long orderId) { // 1. 获取采购订单 ErpPurchaseOrderDO order = validatePurchaseOrderExists(orderId); // 2. 获取采购订单明细 List items = purchaseOrderItemMapper.selectListByOrderId(orderId); if (CollUtil.isEmpty(items)) { return; } // 3. 计算入库状态和总入库数量 int inStatus = calculateInStatus(items); BigDecimal totalInCount = calculateTotalInCount(items); // 4. 更新采购订单入库状态和入库数量 purchaseOrderMapper.updateById(new ErpPurchaseOrderDO() .setId(orderId).setInStatus(inStatus).setInCount(totalInCount)); // 5. 回写采购申请明细的入库数量和采购申请的入库状态 updatePurchaseRequestInStatus(items, inStatus); } /** * 计算总入库数量 */ private BigDecimal calculateTotalInCount(List items) { BigDecimal total = BigDecimal.ZERO; for (ErpPurchaseOrderItemDO item : items) { if (item.getInCount() != null) { total = total.add(item.getInCount()); } } return total; } /** * 回写采购申请入库数量和入库状态 * * @param orderItems 采购订单明细列表 * @param orderInStatus 采购订单入库状态 */ private void updatePurchaseRequestInStatus(List orderItems, int orderInStatus) { // 获取所有关联的采购申请明细 ID Set requestItemIds = new HashSet<>(); for (ErpPurchaseOrderItemDO item : orderItems) { if (item.getRequestItemId() != null) { requestItemIds.add(item.getRequestItemId()); } } if (requestItemIds.isEmpty()) { return; } // 更新采购申请明细的入库数量 for (ErpPurchaseOrderItemDO orderItem : orderItems) { if (orderItem.getRequestItemId() != null && orderItem.getInCount() != null) { purchaseRequestItemMapper.updateById(new ErpPurchaseRequestItemDO() .setId(orderItem.getRequestItemId()) .setInCount(orderItem.getInCount())); } } // 获取采购申请明细,找到对应的采购申请 ID List requestItems = purchaseRequestItemMapper.selectBatchIds(requestItemIds); if (CollUtil.isEmpty(requestItems)) { return; } Set requestIds = convertSet(requestItems, ErpPurchaseRequestItemDO::getRequestId); // 更新采购申请的入库状态 for (Long requestId : requestIds) { purchaseRequestMapper.updateById(new ErpPurchaseRequestDO() .setId(requestId) .setInStatus(orderInStatus)); } } /** * 计算入库状态 * * @param items 采购订单明细列表 * @return 入库状态 */ private int calculateInStatus(List items) { boolean allIn = true; boolean anyIn = false; for (ErpPurchaseOrderItemDO item : items) { BigDecimal count = item.getCount() != null ? item.getCount() : BigDecimal.ZERO; BigDecimal inCount = item.getInCount() != null ? item.getInCount() : BigDecimal.ZERO; if (inCount.compareTo(BigDecimal.ZERO) > 0) { anyIn = true; } if (inCount.compareTo(count) < 0) { allIn = false; } } if (allIn) { return ErpPurchaseOrderInStatusEnum.ALL_IN.getStatus(); } else if (anyIn) { return ErpPurchaseOrderInStatusEnum.PART_IN.getStatus(); } else { return ErpPurchaseOrderInStatusEnum.NOT_IN.getStatus(); } } @Override @Transactional(rollbackFor = Exception.class) public Long confirmReceipt(Long id) { // 1. 校验采购订单存在且已审核 ErpPurchaseOrderDO purchaseOrder = validatePurchaseOrder(id); // 2. 校验采购订单未全部入库 if (ErpPurchaseOrderInStatusEnum.ALL_IN.getStatus().equals(purchaseOrder.getInStatus())) { throw exception(PURCHASE_ORDER_ALL_IN); } // 3. 调用 MES 接口生成到货通知单 Long arrivalNoticeId = arrivalNoticeApi.generateArrivalNoticeFromPurchaseOrder(id); log.info("[confirmReceipt] 采购订单({}) 确认收货,生成到货通知单({})", id, arrivalNoticeId); return arrivalNoticeId; } }