gaoluyang
6 天以前 006020bc9a87dc40c2e73bc50f244b348b831de1
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java
@@ -7,7 +7,6 @@
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns.ErpPurchaseReturnPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns.ErpPurchaseReturnSaveReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnItemDO;
@@ -15,15 +14,16 @@
import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseReturnMapper;
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.stock.ErpStockRecordBizTypeEnum;
import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService;
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
import cn.iocoder.yudao.module.erp.service.stock.ErpStockRecordService;
import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO;
import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
import cn.iocoder.yudao.module.mes.api.wms.dto.WmsPurchaseInboundReqDTO;
import cn.iocoder.yudao.module.mes.api.wms.stock.WmsStockApi;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import java.math.BigDecimal;
@@ -31,6 +31,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
@@ -45,6 +46,7 @@
 */
@Service
@Validated
@Slf4j
public class ErpPurchaseReturnServiceImpl implements ErpPurchaseReturnService {
    @Resource
@@ -56,14 +58,14 @@
    private ErpNoRedisDAO noRedisDAO;
    @Resource
    private ErpProductService productService;
    private MdmItemApi mdmItemApi;
    @Resource
    @Lazy // 延迟加载,避免循环依赖
    private ErpPurchaseOrderService purchaseOrderService;
    @Resource
    private ErpAccountService accountService;
    @Resource
    private ErpStockRecordService stockRecordService;
    private WmsStockApi wmsStockApi;
    @Override
    @Transactional(rollbackFor = Exception.class)
@@ -171,22 +173,35 @@
            throw exception(approve ? PURCHASE_RETURN_APPROVE_FAIL : PURCHASE_RETURN_PROCESS_FAIL);
        }
        // 3. 变更库存
        List<ErpPurchaseReturnItemDO> purchaseReturnItems = purchaseReturnItemMapper.selectListByReturnId(id);
        Integer bizType = approve ? ErpStockRecordBizTypeEnum.PURCHASE_RETURN.getType()
                : ErpStockRecordBizTypeEnum.PURCHASE_RETURN_CANCEL.getType();
        purchaseReturnItems.forEach(purchaseReturnItem -> {
            BigDecimal count = approve ? purchaseReturnItem.getCount().negate() : purchaseReturnItem.getCount();
            ErpStockRecordCreateReqBO stockRecordBO = new ErpStockRecordCreateReqBO();
            stockRecordBO.setProductId(purchaseReturnItem.getProductId());
            stockRecordBO.setWarehouseId(purchaseReturnItem.getWarehouseId());
            stockRecordBO.setCount(count);
            stockRecordBO.setBizType(bizType);
            stockRecordBO.setBizId(purchaseReturnItem.getReturnId());
            stockRecordBO.setBizItemId(purchaseReturnItem.getId());
            stockRecordBO.setBizNo(purchaseReturn.getNo());
            stockRecordService.createStockRecord(stockRecordBO);
        });
        // 3. 审核通过时,同步 MES 仓储存货(采购退货出库)
        if (approve) {
            syncToWmsPurchaseReturnOutbound(purchaseReturn);
        }
    }
    /**
     * 同步采购退货到 WMS(MES 仓储)库存
     */
    private void syncToWmsPurchaseReturnOutbound(ErpPurchaseReturnDO purchaseReturn) {
        List<ErpPurchaseReturnItemDO> purchaseReturnItems = purchaseReturnItemMapper.selectListByReturnId(purchaseReturn.getId());
        if (CollUtil.isEmpty(purchaseReturnItems)) {
            return;
        }
        WmsPurchaseInboundReqDTO reqDTO = new WmsPurchaseInboundReqDTO()
                .setBizId(purchaseReturn.getId())
                .setBizCode(purchaseReturn.getNo())
                .setVendorId(purchaseReturn.getSupplierId())
                .setReceiptTime(purchaseReturn.getReturnTime())
                .setItems(convertList(purchaseReturnItems, item -> new WmsPurchaseInboundReqDTO.Item()
                        .setItemId(item.getProductId())
                        .setWarehouseId(item.getWarehouseId())
                        .setQuantity(item.getCount())
                        .setBizLineId(item.getId())));
        try {
            wmsStockApi.purchaseReturnOutbound(reqDTO);
        } catch (Exception e) {
            log.error("[syncToWmsPurchaseReturnOutbound] 同步失败,purchaseReturnId={}", purchaseReturn.getId(), e);
        }
    }
    @Override
@@ -202,13 +217,15 @@
    }
    private List<ErpPurchaseReturnItemDO> validatePurchaseReturnItems(List<ErpPurchaseReturnSaveReqVO.Item> list) {
        // 1. 校验产品存在
        List<ErpProductDO> productList = productService.validProductList(
                convertSet(list, ErpPurchaseReturnSaveReqVO.Item::getProductId));
        Map<Long, ErpProductDO> productMap = convertMap(productList, ErpProductDO::getId);
        // 1. 校验物料存在(物料主数据已迁移到 MDM)
        Set<Long> productIds = convertSet(list, ErpPurchaseReturnSaveReqVO.Item::getProductId);
        Map<Long, MdmItemRespDTO> itemMap = productIds.isEmpty() ? Collections.emptyMap() : mdmItemApi.getItemMap(productIds);
        if (itemMap.size() != productIds.size()) {
            throw exception(PRODUCT_NOT_EXISTS);
        }
        // 2. 转化为 ErpPurchaseReturnItemDO 列表
        return convertList(list, o -> BeanUtils.toBean(o, ErpPurchaseReturnItemDO.class, item -> {
            item.setProductUnitId(productMap.get(item.getProductId()).getUnitId());
            item.setProductUnitId(itemMap.get(item.getProductId()).getUnitMeasureId());
            item.setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount()));
            if (item.getTotalPrice() == null) {
                return;