
package com.tmerclub.cloud.order.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.tmerclub.cloud.api.delivery.dto.DeliveryOrderDTO;
import com.tmerclub.cloud.api.delivery.vo.StationVO;
import com.tmerclub.cloud.api.dto.PurchaseOrderUpdateDTO;
import com.tmerclub.cloud.api.feign.SearchPurchaseOrderFeignClient;
import com.tmerclub.cloud.api.multishop.feign.ShopDetailFeignClient;
import com.tmerclub.cloud.api.multishop.vo.ShopDetailVO;
import com.tmerclub.cloud.api.order.bo.EsPurchaseOrderBO;
import com.tmerclub.cloud.api.product.dto.SkuStockLockDTO;
import com.tmerclub.cloud.api.product.dto.WarehouseSearchDTO;
import com.tmerclub.cloud.api.product.feign.*;
import com.tmerclub.cloud.api.product.vo.SkuStockVO;
import com.tmerclub.cloud.api.supplier.bo.SupplierDetailBO;
import com.tmerclub.cloud.api.supplier.feign.SupplierDetailFeignClient;
import com.tmerclub.cloud.api.supplier.vo.SupplierApiDetailVO;
import com.tmerclub.cloud.common.cache.constant.LuaOperateEnum;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.constant.SysTypeEnum;
import com.tmerclub.cloud.common.product.constant.StockPointType;
import com.tmerclub.cloud.common.product.dto.StockPointSkuDTO;
import com.tmerclub.cloud.common.constant.PurchaseAmountType;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.i18n.I18nMessage;
import com.tmerclub.cloud.common.i18n.LanguageEnum;
import com.tmerclub.cloud.common.order.bo.PurchaseAmountLogBO;
import com.tmerclub.cloud.common.order.constant.DeliveryType;
import com.tmerclub.cloud.common.product.constant.StockBillStatus;
import com.tmerclub.cloud.common.product.constant.StockBillType;
import com.tmerclub.cloud.common.product.constant.StockType;
import com.tmerclub.cloud.common.product.vo.*;
import com.tmerclub.cloud.common.response.ResponseEnum;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
import com.tmerclub.cloud.common.rocketmq.config.RocketMqConstant;
import com.tmerclub.cloud.common.security.AuthUserContext;
import com.tmerclub.cloud.common.util.Arith;
import com.tmerclub.cloud.common.util.BeanUtil;
import com.tmerclub.cloud.common.util.ExcelUtil;
import com.tmerclub.cloud.common.util.LangUtil;
import com.tmerclub.cloud.delivery.manager.DeliveryManager;
import com.tmerclub.cloud.delivery.service.StationService;
import com.tmerclub.cloud.common.order.vo.WarehouseVO;
import com.tmerclub.cloud.order.bo.mongo.MongoPurchaseOrderBO;
import com.tmerclub.cloud.order.bo.mongo.MongoPurchaseOrderItemBO;
import com.tmerclub.cloud.order.constant.PurchasesStatusEnum;
import com.tmerclub.cloud.order.dto.PurchaseOrderDTO;
import com.tmerclub.cloud.order.dto.PurchaseOrderItemDTO;
import com.tmerclub.cloud.order.listener.PurchaseExcelListener;
import com.tmerclub.cloud.order.manager.MongoPurchaseOrderManager;
import com.tmerclub.cloud.order.mapper.PurchaseOrderItemMapper;
import com.tmerclub.cloud.order.mapper.PurchaseOrderMapper;
import com.tmerclub.cloud.order.model.*;
import com.tmerclub.cloud.order.service.*;
import com.tmerclub.cloud.order.model.*;
import com.tmerclub.cloud.order.service.*;
import com.tmerclub.cloud.order.vo.PurchaseOrderItemVO;
import com.tmerclub.cloud.order.vo.PurchaseOrderVO;
import com.tmerclub.cloud.order.vo.PurchaseSpuExcelVO;
import com.tmerclub.cloud.order.vo.PurchaseSpuImportVO;
import io.seata.spring.annotation.GlobalTransactional;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 采购订单
 *
 * @author lhd
 * @date 2022-06-22 17:12:02
 */
@Service
public class PurchaseOrderServiceImpl implements PurchaseOrderService {

    private static final Logger log = LoggerFactory.getLogger(PurchaseOrderServiceImpl.class);

    @Autowired
    private PurchaseOrderMapper purchaseOrderMapper;
    @Autowired
    private DeliveryManager deliveryManager;
    @Autowired
    private PurchaseOrderItemMapper purchaseOrderItemMapper;
    @Autowired
    private PurchaseOrderLangService purchaseOrderLangService;
    @Autowired
    private PurchaseOrderItemService purchaseOrderItemService;
    @Autowired
    private MongoPurchaseOrderManager mongoPurchaseOrderManager;
    @Autowired
    private PurchaseOrderAddrService purchaseOrderAddrService;
    @Autowired
    private PurchaseOrderItemLangService purchaseOrderItemLangService;
    @Autowired
    private StationService stationService;
    @Autowired
    private RocketMQTemplate stockBillLogPurchaseStorageTemplate;
    @Autowired
    private RocketMQTemplate addPurchaseAmountLogTemplate;
    @DubboReference
    private WarehouseFeignClient warehouseFeignClient;
    @DubboReference
    private SupplierDetailFeignClient supplierDetailFeignClient;
    @DubboReference
    private SpuFeignClient spuFeignClient;
    @DubboReference
    private SkuFeignClient skuFeignClient;
    @DubboReference
    private ShopDetailFeignClient shopDetailFeignClient;
    @DubboReference
    private SkuStockChangeFeignClient skuStockChangeFeignClient;
    @DubboReference
    private SearchPurchaseOrderFeignClient searchPurchaseOrderFeignClient;
    @DubboReference
    private SkuStockFeignClient skuStockFeignClient;
    @DubboReference
    private CategoryShopFeignClient categoryShopFeignClient;
    @DubboReference
    private StockPointFeignClient stockPointFeignClient;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void savePurchaseOrder(PurchaseOrderDTO purchaseOrderDTO) {
        long begintTimeMillis = System.currentTimeMillis();
        // 获取商家仓库
        WarehouseVO warehouse = this.checkWarehouse(purchaseOrderDTO.getWarehouseId(), purchaseOrderDTO.getShopId(), SysTypeEnum.MULTISHOP.value());
        purchaseOrderDTO.setStockPointType(Objects.equals(warehouse.getSysType(), SysTypeEnum.STATION.value()) ? StockPointType.STATION.getValue() : StockPointType.WAREHOUSE.getValue());
        // 获取供应商仓库
        WarehouseSearchDTO warehouseDTO = new WarehouseSearchDTO();
        warehouseDTO.setAreaId(warehouse.getAreaId());
        warehouseDTO.setSysType(SysTypeEnum.SUPPLIER.value());
        warehouseDTO.setShopIds(Collections.singletonList(purchaseOrderDTO.getSupplierId()));
        List<WarehouseVO> warehouses = warehouseFeignClient.listCanDeliveryWarehouse(warehouseDTO);
        if (CollectionUtils.isEmpty(warehouses)) {
            throw new LuckException("含有当前仓库不能采购的商品");
        }
        log.info("savePurchaseOrder-warehouseFeignClient, 执行时间：{}", System.currentTimeMillis() - begintTimeMillis);
        WarehouseVO supplierWarehouse = warehouses.get(0);
        // 检查商品是否为该供应商仓库商品
        List<Long> skuIds = purchaseOrderDTO.getPurchaseOrderItemList().stream().map(PurchaseOrderItemDTO::getSkuId).collect(Collectors.toList());
        List<Long> containSkuIds = skuStockFeignClient.checkStockPointContainSku(Collections.singletonList(supplierWarehouse.getWarehouseId()), skuIds);
        log.info("savePurchaseOrder-skuStockFeignClient, 执行时间：{}", System.currentTimeMillis() - begintTimeMillis);
        if (!Objects.equals(skuIds.size(), containSkuIds.size())) {
            throw new LuckException("含有该仓库/门店不能采购的商品");
        }
        // 检查sku库存是否充足，并锁定库存-- 生成采购订单再进行库存的扣除
        List<SkuStockLockDTO> skuStockLockList = this.checkStock(purchaseOrderDTO, supplierWarehouse.getWarehouseId());
        ServerResponseEntity<ShopDetailVO> shopDetailResp = shopDetailFeignClient.getShopDetailByShopId(purchaseOrderDTO.getShopId());
        log.info("savePurchaseOrder-shopDetailResp, 执行时间：{}", System.currentTimeMillis() - begintTimeMillis);
        if (!shopDetailResp.isSuccess()) {
            throw new LuckException(shopDetailResp.getMsg());
        }
        List<SkuVO> skuList = getSkuVOList(purchaseOrderDTO);
        Map<Long, SpuAndSkuVO> spuAndSkuMap = getSpuAndSkuMap(purchaseOrderDTO, skuList);
        double totalAmount = 0.0D;
        int totalStock = 0;
        List<PurchaseOrderItem> purchaseOrderItemList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        // 订单商品中文名称
        StringBuilder orderSpuNameCn = new StringBuilder(100);
        // 订单商品英文名称
        StringBuilder orderSpuNameEn = new StringBuilder(100);
        // 商品排序，同spu放相邻位置
        List<PurchaseOrderItemDTO> purchaseOrderItemDTOS = this.sortPurchaseItem(purchaseOrderDTO.getPurchaseOrderItemList());
        for (PurchaseOrderItemDTO purchaseOrderItemDTO : purchaseOrderItemDTOS) {
            purchaseOrderItemDTO.setInboundStock(purchaseOrderItemDTO.getPurchaseStock());
            PurchaseOrderItem purchaseOrderItem = BeanUtil.map(purchaseOrderItemDTO, PurchaseOrderItem.class);
            SpuAndSkuVO spuAndSkuVO = spuAndSkuMap.get(purchaseOrderItem.getSkuId());
            SpuVO spu = spuAndSkuVO.getSpu();
            SkuVO sku = spuAndSkuVO.getSku();
            setPurchaseInfo(purchaseOrderDTO, orderSpuNameCn, orderSpuNameEn, purchaseOrderItem, spu, sku);
            purchaseOrderItemList.add(purchaseOrderItem);
            totalAmount = Arith.add(totalAmount, purchaseOrderItem.getPurchaseAmount());
            totalStock += purchaseOrderItem.getPurchaseStock();
        }

        // 1.保存订单地址
        if (Objects.isNull(shopDetailResp.getData())) {
            // 请填写收货地址
            throw new LuckException("请先去填写店铺收货地址");
        }
        PurchaseOrderAddr purchaseOrderAddr = getAndSavePurchaseOrderAddr(purchaseOrderDTO, warehouse);

        // 2.保存订单信息
        Date date = new Date();
        purchaseOrderDTO.setCreateTime(date);
        purchaseOrderDTO.setUpdateTime(date);
        purchaseOrderDTO.setSupplierWarehouseId(supplierWarehouse.getWarehouseId());
        purchaseOrderDTO.setTotalAmount(totalAmount);
        purchaseOrderDTO.setTotalStock(totalStock);
        purchaseOrderDTO.setActualTotalStock(0);
        purchaseOrderDTO.setStatus(PurchasesStatusEnum.UNPAY.value());

        PurchaseOrder purchaseOrder = BeanUtil.map(purchaseOrderDTO, PurchaseOrder.class);
        // 1.设置配送方式
        purchaseOrder.setDeliveryType(DeliveryType.DELIVERY.value());
        purchaseOrder.setPurchaseOrderAddrId(purchaseOrderAddr.getPurchaseOrderAddrId());
        purchaseOrderMapper.save(purchaseOrder);
        log.info("savePurchaseOrder-purchaseOrderMapper, 执行时间：{}", System.currentTimeMillis() - begintTimeMillis);
        // 2.处理下订单商品语言
        orderSpuNameCn = new StringBuilder(orderSpuNameCn.subSequence(0, Math.min(orderSpuNameCn.length() - 1, 100)));
        if (orderSpuNameCn.lastIndexOf(StrUtil.COMMA) == orderSpuNameCn.length() - 1) {
            orderSpuNameCn.deleteCharAt(orderSpuNameCn.length() - 1);
        }
        if (StrUtil.isNotBlank(orderSpuNameEn)) {
            orderSpuNameEn = new StringBuilder(orderSpuNameEn.subSequence(0, Math.min(orderSpuNameEn.length() - 1, 100)));
            if (orderSpuNameEn.lastIndexOf(StrUtil.COMMA) == orderSpuNameEn.length() - 1) {
                orderSpuNameEn.deleteCharAt(orderSpuNameEn.length() - 1);
            }
        }
        purchaseOrderLangService.saveBatch(orderSpuNameCn, orderSpuNameEn, purchaseOrder.getPurchaseOrderId());
        log.info("savePurchaseOrder-purchaseOrderLangService, 执行时间：{}", System.currentTimeMillis() - begintTimeMillis);

        purchaseOrderItemMapper.saveBatch(purchaseOrderItemList);
        log.info("savePurchaseOrder-purchaseOrderItemMapper, 执行时间：{}", System.currentTimeMillis() - begintTimeMillis);

        // 3.保存订单商品名称
        purchaseOrderItemLangService.saveOrderItemLang(purchaseOrderItemList);
        log.info("savePurchaseOrder-purchaseOrderItemLangService, 执行时间：{}", System.currentTimeMillis() - begintTimeMillis);

        // 4.采购的商品未导入时自动导入供应商商品
        voluntarilyImportSupplierSpu(purchaseOrderDTO);
        // 库存解锁
        skuStockChangeFeignClient.purchaseOrderReduceLockStock(skuStockLockList);
        log.info("savePurchaseOrder-skuStockChangeFeignClient, 执行时间：{}", System.currentTimeMillis() - begintTimeMillis);
        // 更新仓库和商品关系
        stockPointFeignClient.updateStockPointSkuRelate(Collections.singletonList(supplierWarehouse.getWarehouseId()), skuIds);
        log.info("savePurchaseOrder-stockPointFeignClient, 执行时间：{}", System.currentTimeMillis() - begintTimeMillis);
        // 供应商新增采购出库记录
        purchaseOrderDTO.setSysType(SysTypeEnum.SUPPLIER.value());
        StockBillLogVO stockBillLog = this.buildStockBillLog(purchaseOrderDTO, supplierWarehouse.getWarehouseId(), StockBillType.PURCHASE_OUTBOUND);
        TransactionSendResult transactionSendResult = stockBillLogPurchaseStorageTemplate.sendMessageInTransaction(RocketMqConstant.STOCK_BILL_LOG_PURCHASE_STORAGE_TOPIC, new GenericMessage<>(stockBillLog), stockBillLog);
        log.info("savePurchaseOrder-transactionSendResult, 执行时间：{}", System.currentTimeMillis() - begintTimeMillis);
        if (!Objects.equals(transactionSendResult.getLocalTransactionState(), LocalTransactionState.COMMIT_MESSAGE)) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
    }

    @Override
    public PurchaseOrderVO info(Long purchaseOrderId, Long supplierId) {
        PurchaseOrderVO purchaseOrder = purchaseOrderMapper.info(purchaseOrderId, supplierId, I18nMessage.getLang());
        if (Objects.isNull(purchaseOrder)) {
            throw new LuckException("采购订单不存在");
        }
        // 补充店铺信息
        ServerResponseEntity<ShopDetailVO> shopResp = shopDetailFeignClient.getShopDetailByShopId(purchaseOrder.getShopId());
        if (!shopResp.isSuccess()) {
            throw new LuckException(shopResp.getMsg());
        }
        purchaseOrder.setShopName(shopResp.getData().getMerchantName());
        // 补充供应商信息
        ServerResponseEntity<SupplierDetailBO> supplierResp = supplierDetailFeignClient.getSupplierBySupplierId(purchaseOrder.getSupplierId());
        if (!supplierResp.isSuccess()) {
            throw new LuckException(supplierResp.getMsg());
        }
        purchaseOrder.setSupplierName(supplierResp.getData().getSupplierName());
        // 补充仓库信息
        if (!Objects.isNull(purchaseOrder.getWarehouseId())) {
            WarehouseVO warehouse = warehouseFeignClient.getWarehouseById(purchaseOrder.getWarehouseId());
            if (!Objects.isNull(warehouse)) {
                purchaseOrder.setWarehouseName(warehouse.getWarehouseName());
            }
        }
        // 订单商品多语言处理
        orderLangHandle(purchaseOrder);
        return purchaseOrder;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void delivery(DeliveryOrderDTO deliveryOrderParam) {
        PurchaseOrderVO purchaseOrderVO = purchaseOrderMapper.info(deliveryOrderParam.getOrderId(), AuthUserContext.get().getTenantId(), I18nMessage.getLang());
        deliveryOrderParam.setUserId(purchaseOrderVO.getShopId());
        deliveryOrderParam.setOrderAddrId(purchaseOrderVO.getPurchaseOrderAddrId());
        purchaseOrderItemService.updateByDeliveries(deliveryOrderParam.getSelectOrderItems(), deliveryOrderParam.getDeliveryType());
        // 算下未发货商品数量
        int unDeliveryNum = purchaseOrderItemService.countUnDeliveryNumByOrderId(deliveryOrderParam.getOrderId());
        //修改为发货状态
        if (Objects.equals(unDeliveryNum, 0)) {
            Date date = new Date();
            PurchaseOrder order = new PurchaseOrder();
            order.setPurchaseOrderId(deliveryOrderParam.getOrderId());
            order.setStatus(PurchasesStatusEnum.DELIVERY.value());
            order.setUpdateTime(date);
            order.setDeliveryTime(date);
            //判断是无需物流还是快递发货,如果是无需快递，则判断该订单是否包含有物流的项，若有物流则配送类型为快递配送，没有物流则不变
            if (purchaseOrderItemService.getDevTypeByOrderId(deliveryOrderParam.getOrderId())) {
                order.setDeliveryType(DeliveryType.DELIVERY.value());
            } else {
                order.setDeliveryType(deliveryOrderParam.getDeliveryType());
            }
            purchaseOrderMapper.updateByPurchaseId(order);
            purchaseOrderItemService.updateStatusByPurchaseOrderId(PurchasesStatusEnum.DELIVERY.value(), order.getPurchaseOrderId());
            updatePurchaseOrderStatus(order);
        }
        // 先更改订单状态，再保存包裹信息
        deliveryManager.saveDeliveryInfo(deliveryOrderParam, 1, 0);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePayVoucher(PurchaseOrderDTO purchaseOrder) {
        PurchaseOrder purchaseOrderDb = purchaseOrderMapper.getByPurchaseOrderId(purchaseOrder.getPurchaseOrderId());
        if (!Objects.equals(purchaseOrderDb.getShopId(), purchaseOrder.getShopId())) {
            throw new LuckException(ResponseEnum.UNAUTHORIZED);
        }
        if (!Objects.equals(purchaseOrderDb.getStatus(), PurchasesStatusEnum.UNPAY.value())) {
            throw new LuckException("此订单状态已改变，不能进行此操作");
        }
        purchaseOrderDb.setVoucherImgUrls(purchaseOrder.getVoucherImgUrls());
        purchaseOrderDb.setStatus(PurchasesStatusEnum.WAITAUDIT.value());
        purchaseOrderMapper.updateByPurchaseId(purchaseOrderDb);
        purchaseOrderItemService.updateStatusByPurchaseOrderId(purchaseOrderDb.getStatus(), purchaseOrderDb.getPurchaseOrderId());
        updatePurchaseOrderStatus(purchaseOrderDb);
        // 新增采购金额日志
        this.addPurchaseAmountLog(purchaseOrderDb, PurchaseAmountType.IN_OR_OUT.getValue());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void auditVoucher(PurchaseOrderDTO purchaseOrder) {
        PurchaseOrder purchaseOrderDb = purchaseOrderMapper.getByPurchaseOrderId(purchaseOrder.getPurchaseOrderId());
        if (!Objects.equals(purchaseOrder.getSupplierId(), purchaseOrderDb.getSupplierId())) {
            throw new LuckException(ResponseEnum.UNAUTHORIZED);
        }
        if (!Objects.equals(purchaseOrderDb.getStatus(), PurchasesStatusEnum.WAITAUDIT.value())) {
            throw new LuckException("此订单状态已改变，不能进行此操作");
        }
        // 1-审核通过
        if (Objects.equals(purchaseOrder.getStatus(), 1)) {
            purchaseOrderDb.setStatus(PurchasesStatusEnum.WAIT_STOCK.value());
            // 0-审核不通过
        } else if (Objects.equals(purchaseOrder.getStatus(), 0)) {
            purchaseOrderDb.setStatus(PurchasesStatusEnum.VOIDED.value());
            // 审核不通过，采购订单作废
            this.reductionStock(purchaseOrderMapper.info(purchaseOrderDb.getPurchaseOrderId(), purchaseOrderDb.getSupplierId(), I18nMessage.getLang()));
            // 新增采购金额作废日志
            this.addPurchaseAmountLog(purchaseOrderDb, PurchaseAmountType.CANCEL.getValue());
        } else {
            return;
        }
        purchaseOrderMapper.updateByPurchaseId(purchaseOrderDb);
        purchaseOrderItemService.updateStatusByPurchaseOrderId(purchaseOrderDb.getStatus(), purchaseOrderDb.getPurchaseOrderId());
        updatePurchaseOrderStatus(purchaseOrderDb);
    }

    /**
     * 更新供应商订单时，手动更新状态
     * 更新状态失败后续还有canal监听进行更新，优先原本功能的执行，所以不能抛出异常
     *
     * @param order
     */
    private void updatePurchaseOrderStatus(PurchaseOrder order) {
        try {
            searchPurchaseOrderFeignClient.updatePurchaseOrderStatus(new PurchaseOrderUpdateDTO(order.getPurchaseOrderId(), order.getStatus()));
        } catch (Exception e) {
            log.error("供应商订单更新状态失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void inbound(PurchaseOrderDTO purchaseOrderDTO) {
        if (CollectionUtils.isEmpty(purchaseOrderDTO.getPurchaseOrderItemList())) {
            throw new LuckException("入库商品为空");
        }
        // 过滤出入库数量不为0的数据，并转成Map
        Map<Long, PurchaseOrderItemDTO> itemMap = purchaseOrderDTO.getPurchaseOrderItemList().stream()
                .filter(x -> x.getActualStock() > 0)
                .collect(Collectors.toMap(PurchaseOrderItemDTO::getSkuId, x -> x));
        if (CollectionUtils.isEmpty(itemMap)) {
            throw new LuckException("入库商品为空");
        }
        // 检查采购订单
        PurchaseOrderVO purchaseOrderDb = this.checkPurchaseOrder(purchaseOrderDTO.getPurchaseOrderId(), purchaseOrderDTO.getShopId());
        if (Objects.equals(purchaseOrderDb.getStatus(), PurchasesStatusEnum.UNPAY.value())) {
            throw new LuckException("采购订单未付款");
        }
        if (Objects.equals(purchaseOrderDb.getStatus(), PurchasesStatusEnum.WAIT_STOCK.value())) {
            throw new LuckException("采购订单未发货");
        }
        // 更新采购商品入库数量以及状态
        List<PurchaseOrderItemVO> updateItems = new ArrayList<>(Constant.INITIAL_CAPACITY);
        Integer actualTotalStock = 0;
        boolean complete = true;
        PurchaseOrderItemDTO purchaseOrderItemDTO;
        for (PurchaseOrderItemVO dbItem : purchaseOrderDb.getPurchaseOrderItemList()) {
            purchaseOrderItemDTO = itemMap.get(dbItem.getSkuId());
            if (!Objects.isNull(purchaseOrderItemDTO)) {
                if (purchaseOrderItemDTO.getActualStock() > dbItem.getPurchaseStock() - dbItem.getActualStock()) {
                    throw new LuckException("商品入库数量不可以大于采购数量");
                }
                dbItem.setActualStock(dbItem.getActualStock() + purchaseOrderItemDTO.getActualStock());
                dbItem.setStatus(Objects.equals(dbItem.getPurchaseStock(), dbItem.getActualStock()) ? PurchasesStatusEnum.COMPLETION.value() : PurchasesStatusEnum.PARTIALLY_STOCK.value());
                updateItems.add(dbItem);
            }
            complete = complete && Objects.equals(dbItem.getPurchaseStock(), dbItem.getActualStock());
            actualTotalStock += dbItem.getActualStock();
        }
        // 更新采购订单商品
        List<PurchaseOrderItem> purchaseOrderItems = BeanUtil.mapAsList(updateItems, PurchaseOrderItem.class);
        purchaseOrderItemService.updateBatchById(purchaseOrderItems);
        // 更新采购订单
        PurchaseOrder purchaseOrder = BeanUtil.map(purchaseOrderDb, PurchaseOrder.class);
        purchaseOrder.setDeliverTime(new Date());
        purchaseOrder.setRemark(purchaseOrderDTO.getRemark());
        purchaseOrder.setActualTotalStock(actualTotalStock);
        purchaseOrder.setStatus(complete ? PurchasesStatusEnum.COMPLETION.value() : PurchasesStatusEnum.PARTIALLY_STOCK.value());
        purchaseOrderMapper.updateByPurchaseId(purchaseOrder);
        // 新增库存（商家自己的代销商品库存）
        List<PurchaseOrderItemDTO> saleItems = this.buildSalePurchaseOrderItem(purchaseOrderDTO.getShopId(), updateItems);
        List<SkuStockVO> skuStockVOList = new ArrayList<>(saleItems.size());
        for (PurchaseOrderItemDTO saleItem : saleItems) {
            PurchaseOrderItemDTO itemDTO = itemMap.get(saleItem.getSupplierSkuId());
            saleItem.setInboundStock(itemDTO.getActualStock());
            skuStockVOList.add(this.buildSkuStockVO(saleItem, purchaseOrderDb.getWarehouseId(), LuaOperateEnum.SKU_ADD));
        }
        skuStockFeignClient.changeSkuStock(skuStockVOList);
        // 新增库存流水日志
        purchaseOrderDTO = new PurchaseOrderDTO();
        BeanUtils.copyProperties(purchaseOrder, purchaseOrderDTO);
        purchaseOrderDTO.setSysType(SysTypeEnum.MULTISHOP.value());
        purchaseOrderDTO.setPurchaseOrderItemList(saleItems);
        StockBillLogVO stockBillLog = this.buildStockBillLog(purchaseOrderDTO, purchaseOrderDTO.getWarehouseId(), StockBillType.PURCHASE_STORAGE);
        TransactionSendResult transactionSendResult = stockBillLogPurchaseStorageTemplate.sendMessageInTransaction(RocketMqConstant.STOCK_BILL_LOG_PURCHASE_STORAGE_TOPIC, new GenericMessage<>(stockBillLog), stockBillLog);
        if (!Objects.equals(transactionSendResult.getLocalTransactionState(), LocalTransactionState.COMMIT_MESSAGE)) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
        // 更新商家代销商品信息（触发canal，从而更新es数据）
        List<Long> supplierSpuIds = purchaseOrderDb.getPurchaseOrderItemList().stream().map(PurchaseOrderItemVO::getSpuId).collect(Collectors.toList());
        List<SpuVO> spuList = spuFeignClient.listShopSpuBySupplierSpuIds(purchaseOrderDTO.getShopId(), supplierSpuIds);
        if (CollUtil.isNotEmpty(spuList)) {
            spuFeignClient.updateSpuUpdateTimeBySpuIds(spuList.stream().map(SpuVO::getSpuId).collect(Collectors.toList()));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void nullify(Long shopId, Long purchaseOrderId) {
        PurchaseOrderVO purchaseOrderVO = purchaseOrderMapper.info(purchaseOrderId, null, I18nMessage.getLang());
        if (!Objects.equals(purchaseOrderVO.getShopId(), shopId)) {
            throw new LuckException(ResponseEnum.UNAUTHORIZED);
        }
        Integer status = purchaseOrderVO.getStatus();
        if (Objects.equals(purchaseOrderVO.getStatus(), PurchasesStatusEnum.VOIDED.value())) {
            throw new LuckException("此订单已作废");
        }
        purchaseOrderVO.setStatus(PurchasesStatusEnum.VOIDED.value());
        PurchaseOrder purchaseOrder = BeanUtil.map(purchaseOrderVO, PurchaseOrder.class);
        purchaseOrderMapper.updateByPurchaseId(purchaseOrder);
        purchaseOrderItemMapper.updateStatusByPurchaseOrderId(Collections.singletonList(purchaseOrder.getPurchaseOrderId()), PurchasesStatusEnum.VOIDED.value());
        this.updatePurchaseOrderStatus(purchaseOrder);
        boolean isPay = !Objects.equals(PurchasesStatusEnum.UNPAY.value(), status);
        if (isPay) {
            // 新增采购金额作废日志（待付款不用新增）
            this.addPurchaseAmountLog(purchaseOrder, PurchaseAmountType.CANCEL.getValue());
        }
        // 发货后的订单，不需要还原供应商库存
        if (!PurchasesStatusEnum.unDelivery(status)) {
            return;
        }
        // 未发货之前作废订单，需要还原供应商库存
        // 增加供应商的库存数量, 订单只能作废一次，如果报错直接回滚，等待下次操作
        this.reductionStock(purchaseOrderVO);
    }

    @Override
    public void nullifyByWarehouseId(Long warehouseId) {
        // 查询未完成/作废的采购订单
        PurchaseOrderDTO purchaseOrderDTO = new PurchaseOrderDTO();
        purchaseOrderDTO.setWarehouseId(warehouseId);
        purchaseOrderDTO.setNotInStatuses(Arrays.asList(PurchasesStatusEnum.COMPLETION.value(), PurchasesStatusEnum.VOIDED.value()));
        List<MongoPurchaseOrderBO> purchaseOrderBOS = mongoPurchaseOrderManager.listPurchaseOrder(purchaseOrderDTO);
        if (CollectionUtils.isEmpty(purchaseOrderBOS)) {
            return;
        }
        // 循环作废
        for (MongoPurchaseOrderBO purchaseOrderBO : purchaseOrderBOS) {
            PurchaseOrderVO purchaseOrderVO = purchaseOrderMapper.info(purchaseOrderBO.getPurchaseOrderId(), null, I18nMessage.getLang());
            Integer status = purchaseOrderVO.getStatus();
            purchaseOrderVO.setStatus(PurchasesStatusEnum.VOIDED.value());
            PurchaseOrder purchaseOrder = BeanUtil.map(purchaseOrderVO, PurchaseOrder.class);
            purchaseOrderMapper.updateByPurchaseId(purchaseOrder);
            purchaseOrderItemMapper.updateStatusByPurchaseOrderId(Collections.singletonList(purchaseOrder.getPurchaseOrderId()), PurchasesStatusEnum.VOIDED.value());
            this.updatePurchaseOrderStatus(purchaseOrder);
            // 新增采购金额作废日志（待付款不用新增）
            boolean isPay = !Objects.equals(PurchasesStatusEnum.UNPAY.value(), status);
            if (isPay) {
                this.addPurchaseAmountLog(purchaseOrder, PurchaseAmountType.CANCEL.getValue());
            }
            // 发货后的订单，不需要还原供应商库存
            if (!PurchasesStatusEnum.unDelivery(status)) {
                continue;
            }
            // 未发货之前作废订单，需要还原供应商库存
            this.reductionStock(purchaseOrderVO);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void complete(Long shopId, Long purchaseOrderId) {
        PurchaseOrderVO purchaseOrderVO = purchaseOrderMapper.info(purchaseOrderId, null, I18nMessage.getLang());
        if (!Objects.equals(purchaseOrderVO.getShopId(), shopId)) {
            throw new LuckException(ResponseEnum.UNAUTHORIZED);
        }
        if (!Objects.equals(purchaseOrderVO.getStatus(), PurchasesStatusEnum.PARTIALLY_STOCK.value())) {
            throw new LuckException("数据已过期，请刷新页面");
        }
        purchaseOrderVO.setStatus(PurchasesStatusEnum.COMPLETION.value());
        PurchaseOrder purchaseOrder = BeanUtil.map(purchaseOrderVO, PurchaseOrder.class);
        purchaseOrderMapper.updateByPurchaseId(purchaseOrder);
        purchaseOrderItemMapper.updateStatusByPurchaseOrderId(Collections.singletonList(purchaseOrder.getPurchaseOrderId()), PurchasesStatusEnum.COMPLETION.value());
        updatePurchaseOrderStatus(purchaseOrder);
        // 不是全部商品都入库，则新增采购金额作废日志
        if (!Objects.equals(purchaseOrder.getTotalStock(), purchaseOrder.getActualTotalStock())) {
            this.addPurchaseAmountLog(purchaseOrder, PurchaseAmountType.CANCEL.getValue());
        }
    }

    @Override
    public void downloadModel(HttpServletResponse response) {
        List<PurchaseSpuExcelVO> list = new ArrayList<>(Constant.INITIAL_CAPACITY);
        list.add(new PurchaseSpuExcelVO());
        Map<Integer, String[]> map = new HashMap<>(8);
        ExcelWriter excelWriter = null;
        try {
            // 先执行合并策略
            ExcelWriterBuilder excelWriterMerge = ExcelUtil.getExcelWriterMerge(response, PurchaseSpuExcelVO.EXCEL_NAME, PurchaseSpuExcelVO.MERGE_ROW_INDEX, PurchaseSpuExcelVO.MERGE_COLUMN_INDEX);
            // useDefaultStyle false 不需要默认的头部加粗/自动换行样式
            excelWriter = ExcelUtil.getExcelModel(excelWriterMerge, map, 1).useDefaultStyle(false).build();
            // 业务代码
            if (CollUtil.isNotEmpty(list)) {
                // 进行写入操作
                WriteSheet sheetWriter = EasyExcel.writerSheet(PurchaseSpuExcelVO.SHEET_NAME).head(PurchaseSpuExcelVO.class).build();
                excelWriter.write(list, sheetWriter);
            }
        } catch (Exception e) {
            log.error("导出用户信息模板excel失败", e);
        } finally {
            // 千万别忘记finish 会帮忙关闭流
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }

    @Override
    public PurchaseSpuImportVO parseFile(MultipartFile file, Long shopId, Long warehouseId) {
        // 读取excel文件
        Map<String, List<String>> errorMap = new HashMap<>(16);
        List<PurchaseSpuExcelVO> purchaseSpuExcelVOList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        PurchaseExcelListener purchaseExcelListener = new PurchaseExcelListener(errorMap, purchaseSpuExcelVOList);
        try {
            EasyExcel.read(file.getInputStream(), PurchaseSpuExcelVO.class, purchaseExcelListener).sheet().doRead();
        } catch (IOException e) {
            throw new LuckException(e.getMessage());
        }
        if (CollectionUtil.isEmpty(purchaseSpuExcelVOList)) {
            throw new LuckException("导入数据为空，请检查下文件");
        }
        // 检查仓库
        WarehouseVO warehouse = this.checkWarehouse(warehouseId, shopId, SysTypeEnum.MULTISHOP.value());
        // 获取可采购的供应商集合
        List<Long> categoryIds = categoryShopFeignClient.getCategoryIdsByShopId(shopId, SysTypeEnum.MULTISHOP.value()).getData();
        List<Long> supplierIds = categoryShopFeignClient.getSupplyIdByCategoryIds(categoryIds).getData();
        if (CollectionUtils.isEmpty(supplierIds)) {
            throw new LuckException("无可采购的供应商");
        }
        // 查询供应商可配送的仓库
        WarehouseSearchDTO warehouseDTO = new WarehouseSearchDTO();
        warehouseDTO.setShopIds(supplierIds);
        warehouseDTO.setSysType(SysTypeEnum.SUPPLIER.value());
        warehouseDTO.setAreaId(warehouse.getAreaId());
        List<WarehouseVO> canDeliveryWarehouses = warehouseFeignClient.listCanDeliveryWarehouse(warehouseDTO);
        Map<Long, Long> warehouseMap = canDeliveryWarehouses.stream().collect(Collectors.toMap(WarehouseVO::getWarehouseId, WarehouseVO::getShopId));
        // 查询商品，并转成Map
        Map<String, Integer> partyCodeMap = purchaseSpuExcelVOList.stream()
                .collect(Collectors.toMap(PurchaseSpuExcelVO::getPartyCode, PurchaseSpuExcelVO::getPurchaseStock));
        List<SkuVO> skuVOList = skuFeignClient.listByPartyCodes(new ArrayList<>(partyCodeMap.keySet()));
        if (CollectionUtils.isEmpty(skuVOList)) {
            throw new LuckException("导入商品不存在");
        }
        Set<Long> spuIds = new HashSet<>(Constant.INITIAL_CAPACITY);
        List<Long> skuIds = new ArrayList<>(skuVOList.size());
        Map<Long, SkuVO> skuVOMap = new HashMap<>(Constant.INITIAL_CAPACITY);
        for (SkuVO skuVO : skuVOList) {
            spuIds.add(skuVO.getSpuId());
            skuIds.add(skuVO.getSkuId());
            skuVOMap.put(skuVO.getSkuId(), skuVO);
        }
        List<SpuVO> spuVOList = spuFeignClient.listSpuBySpuIds(new ArrayList<>(spuIds)).getData();
        Map<Long, SpuVO> spuVOMap = spuVOList.stream().collect(Collectors.toMap(SpuVO::getSpuId, x -> x));
        // 过滤出可以采购的商品
        StockPointSkuDTO stockPointSkuDTO = new StockPointSkuDTO();
        stockPointSkuDTO.setSkuIds(skuIds);
        stockPointSkuDTO.setStockPointIds(new ArrayList<>(warehouseMap.keySet()));
        List<StockPointSkuVO> stockPointSkuVOList = stockPointFeignClient.listStockPointSku(stockPointSkuDTO);
        if (CollectionUtils.isEmpty(stockPointSkuVOList)) {
            throw new LuckException("无可采购商品");
        }
        // 查询代销商品信息（用于查询商家库存）
        List<SkuVO> saleSkus = skuFeignClient.listShopSaleSku(skuIds, shopId);
        Map<Long, Long> saleSkuMap = new HashMap<>(Constant.INITIAL_CAPACITY);
        if (!CollectionUtils.isEmpty(saleSkus)) {
            saleSkuMap = saleSkus.stream().collect(Collectors.toMap(SkuVO::getSupplierSkuId, SkuVO::getSkuId));
        }
        // 查询商品库存
        List<SkuStockVO> skuStockVOList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (Long skuId : skuIds) {
            for (Long supplierWarehouseId : warehouseMap.keySet()) {
                skuStockVOList.add(new SkuStockVO(skuId, supplierWarehouseId));
            }
        }
        for (Long shopSkuId : saleSkuMap.values()) {
            skuStockVOList.add(new SkuStockVO(shopSkuId, warehouseId));
        }
        Map<String, SkuStockVO> stockMap = skuStockFeignClient.listSkuStock(skuStockVOList);
        // 查询供应商信息
        List<SupplierApiDetailVO> suppliers = supplierDetailFeignClient.listBySupplierIds(new ArrayList<>(warehouseMap.values())).getData();
        Map<Long, SupplierApiDetailVO> supplierMap = suppliers.stream().collect(Collectors.toMap(SupplierApiDetailVO::getSupplierId, x -> x));
        Map<Long, SupplierApiDetailVO> warehouseSupplierMap = new HashMap<>(Constant.INITIAL_CAPACITY);
        for (Map.Entry<Long, Long> entry :warehouseMap.entrySet()) {
            warehouseSupplierMap.put(entry.getKey(), supplierMap.get(entry.getValue()));
        }
        // 构建采购商品excel导入类
        List<PurchaseSpuVO> purchaseSpuList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (StockPointSkuVO stockPointSkuVO : stockPointSkuVOList) {
            purchaseSpuList.add(this.buildPurchaseImportExcel(
                    skuVOMap.get(stockPointSkuVO.getSkuId()), partyCodeMap, spuVOMap,
                    saleSkuMap, stockMap, warehouseSupplierMap, warehouseId, stockPointSkuVO.getStockPointId()
            ));
        }
        // 返回数据
        PurchaseSpuImportVO purchaseSpuImportVO = new PurchaseSpuImportVO();
        purchaseSpuImportVO.setPurchaseSpuList(purchaseSpuList);
        purchaseSpuImportVO.setTips(String.format("检查到%d条商品信息，成功导入%d条商品信息！错误%d条商品信息!", purchaseSpuExcelVOList.size(), purchaseSpuList.size(), purchaseSpuExcelVOList.size() - purchaseSpuList.size()));
        return purchaseSpuImportVO;
    }

    @Override
    public EsPurchaseOrderBO saveMongoAndGetEsInfo(Long purchaseOrderId) {
        MongoPurchaseOrderBO pruchaseOrder = purchaseOrderMapper.getMongoPruchaseOrderInfo(purchaseOrderId);
        loadMongoPurchaseOrderBo(pruchaseOrder);
        mongoPurchaseOrderManager.save(pruchaseOrder);
        return BeanUtil.map(pruchaseOrder, EsPurchaseOrderBO.class);
    }

    private void loadMongoPurchaseOrderBo(MongoPurchaseOrderBO purchaseOrderBO) {
        purchaseOrderBO.setUpdateTime(new Date());
        for (MongoPurchaseOrderItemBO purchaseOrderItem : purchaseOrderBO.getPurchaseOrderItems()) {
            for (PurchaseOrderItemLang purchaseOrderItemLang : purchaseOrderItem.getPurchaseOrderItemLangs()) {
                if (Objects.equals(purchaseOrderItemLang.getLang(), LanguageEnum.LANGUAGE_ZH_CN.getLang())) {
                    purchaseOrderItem.setSpuNameZh(purchaseOrderItemLang.getSpuName());
                    purchaseOrderItem.setSkuNameZh(purchaseOrderItemLang.getSkuName());
                } else if (Objects.equals(purchaseOrderItemLang.getLang(), LanguageEnum.LANGUAGE_EN.getLang())) {
                    purchaseOrderItem.setSpuNameEn(purchaseOrderItemLang.getSpuName());
                    purchaseOrderItem.setSkuNameEn(purchaseOrderItemLang.getSkuName());
                }
            }
            purchaseOrderItem.setPurchaseOrderItemLangs(null);
        }
        for (PurchaseOrderLang purchaseOrderLang : purchaseOrderBO.getPurchaseOrderLangs()) {
            if (Objects.equals(purchaseOrderLang.getLang(), LanguageEnum.LANGUAGE_ZH_CN.getLang())) {
                purchaseOrderBO.setSpuNameZh(purchaseOrderLang.getSpuName());
            } else if (Objects.equals(purchaseOrderLang.getLang(), LanguageEnum.LANGUAGE_EN.getLang())) {
                purchaseOrderBO.setSpuNameEn(purchaseOrderLang.getSpuName());
            }
        }
        purchaseOrderBO.setPurchaseOrderLangs(null);
        ServerResponseEntity<ShopDetailVO> shopDetailResponseEntity = shopDetailFeignClient.getShopDetailByShopId(purchaseOrderBO.getShopId());
        if (!shopDetailResponseEntity.isSuccess()) {
            throw new LuckException(shopDetailResponseEntity.getMsg());
        }
        purchaseOrderBO.setShopName(shopDetailResponseEntity.getData().getShopName());

        ServerResponseEntity<SupplierDetailBO> supplierResponseEntity = supplierDetailFeignClient.getSupplierBySupplierId(purchaseOrderBO.getSupplierId());
        if (!supplierResponseEntity.isSuccess()) {
            throw new LuckException(supplierResponseEntity.getMsg());
        }
        purchaseOrderBO.setSupplierName(supplierResponseEntity.getData().getSupplierName());
    }

    /**
     * 检查采购商品库存
     *
     * @param purchaseOrderDTO
     */
    private List<SkuStockLockDTO> checkStock(PurchaseOrderDTO purchaseOrderDTO, Long warehouseId) {
        List<SkuStockLockDTO> skuStockLocks = new ArrayList<>(purchaseOrderDTO.getPurchaseOrderItemList().size());
        List<PurchaseOrderItemDTO> purchaseOrderItemList = purchaseOrderDTO.getPurchaseOrderItemList();
        for (PurchaseOrderItemDTO purchaseOrderItemDTO : purchaseOrderItemList) {
            skuStockLocks.add(new SkuStockLockDTO(
                    purchaseOrderDTO.getPurchaseOrderId(),
                    warehouseId,
                    purchaseOrderItemDTO.getSkuId(),
                    purchaseOrderItemDTO.getPurchaseStock())
            );
        }
        String stockInfo = skuStockChangeFeignClient.lockPurchaseOrder(skuStockLocks);
        // 提示具体哪个商品sku库存不足, 如果stockInfo是 null 代表代码出问题了，请检查传参是否正确
        if (!stockInfo.contains(Constant.UNDERLINE)) {
            long skuId = Long.parseLong(stockInfo);
            SkuVO skuVO = skuFeignClient.getSkuAndNameById(skuId);
            throw new LuckException(String.format("sku：【%s】 的库存不足", skuVO.getSkuName()));
        }
        return skuStockLocks;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePurchaseOrderStatus(List<Long> purchaseOrderIds, Integer purchaseOrderStatus) {
        List<PurchaseOrderVO> purchaseOrderVOList = purchaseOrderMapper.listByPurchaseOrderIds(purchaseOrderIds);
        List<Long> purchaseOrderIdList = purchaseOrderVOList.stream().map(PurchaseOrderVO::getPurchaseOrderId).collect(Collectors.toList());
        purchaseOrderVOList.forEach(purchaseOrderVO -> {
            purchaseOrderVO.setStatus(purchaseOrderStatus);
            PurchaseOrder purchaseOrder = BeanUtil.map(purchaseOrderVO, PurchaseOrder.class);
            purchaseOrderMapper.updateByPurchaseId(purchaseOrder);
            // 还原库存 - 待付款作废订单
            this.reductionStock(purchaseOrderVO);
            updatePurchaseOrderStatus(purchaseOrder);
        });
        purchaseOrderItemMapper.updateStatusByPurchaseOrderId(purchaseOrderIdList, PurchasesStatusEnum.VOIDED.value());

    }

    @Override
    public Long countUnFinish(Long warehouseId) {
        if (Objects.isNull(warehouseId)) {
            return 0L;
        }
        return mongoPurchaseOrderManager.countUnFinishPurchase(warehouseId);
    }

    /**
     * 订单语言信息处理
     *
     * @param purchaseOrder 订单
     */
    private void orderLangHandle(PurchaseOrderVO purchaseOrder) {
        Integer lang = I18nMessage.getLang();
        for (PurchaseOrderItemVO orderItem : purchaseOrder.getPurchaseOrderItemList()) {
            if (CollUtil.isEmpty(orderItem.getPurchaseOrderItemLangList())) {
                continue;
            }
            Map<Integer, PurchaseOrderItemLang> langMap = orderItem.getPurchaseOrderItemLangList().stream().collect(Collectors.toMap(PurchaseOrderItemLang::getLang, s -> s));
            PurchaseOrderItemLang orderItemLang;
            if (langMap.containsKey(lang)) {
                orderItemLang = langMap.get(lang);
            } else {
                orderItemLang = langMap.get(LanguageEnum.LANGUAGE_ZH_CN.getLang());
            }
            if (Objects.isNull(orderItemLang)) {
                continue;
            }
            orderItem.setSpuName(orderItemLang.getSpuName());
            orderItem.setSkuName(orderItemLang.getSkuName());
        }
    }

    /**
     * 新增采购金额日志
     * @param purchaseOrder 采购订单
     * @param purchaseAmountType 采购金额类型
     */
    private void addPurchaseAmountLog(PurchaseOrder purchaseOrder, Integer purchaseAmountType) {
        int prodCount = 0;
        long changeAmount = 0L;
        if (Objects.equals(purchaseAmountType, PurchaseAmountType.IN_OR_OUT.getValue())) {
            // 金额采购日志
            prodCount = purchaseOrder.getTotalStock();
            changeAmount = BigDecimal.valueOf(purchaseOrder.getTotalAmount()).longValue();
        } else if (Objects.equals(purchaseAmountType, PurchaseAmountType.CANCEL.getValue())) {
            // 金额作废日志
            prodCount = purchaseOrder.getTotalStock() - purchaseOrder.getActualTotalStock();
            if (Objects.equals(prodCount, purchaseOrder.getTotalStock())) {
                // 全部商品作废，作废金额=采购金额
                changeAmount = BigDecimal.valueOf(purchaseOrder.getTotalAmount()).longValue();
            } else {
                // 部分商品作废，计算作废金额
                List<PurchaseOrderItem> orderItems = purchaseOrderItemMapper.listItemByPurchaseOrderId(purchaseOrder.getPurchaseOrderId());
                for (PurchaseOrderItem orderItem : orderItems) {
                    changeAmount += orderItem.getPurchasePrice() * (orderItem.getPurchaseStock() - orderItem.getActualStock());
                }
            }
        }
        // MQ发消息新建日志
        PurchaseAmountLogBO purchaseAmountLogBO = this.buildPurchaseLogBO(purchaseOrder, changeAmount, purchaseAmountType, prodCount);
        addPurchaseAmountLogTemplate.syncSend(RocketMqConstant.ADD_PURCHASE_AMOUNT_LOG_TOPIC, new GenericMessage<>(purchaseAmountLogBO));
    }

    private PurchaseAmountLogBO buildPurchaseLogBO(PurchaseOrder purchaseOrder,
                                                   Long changeAmount,
                                                   Integer purchaseAmountType,
                                                   Integer prodCount) {
        PurchaseAmountLogBO purchaseAmountLogBO = new PurchaseAmountLogBO();
        purchaseAmountLogBO.setPurchaseOrderId(purchaseOrder.getPurchaseOrderId());
        purchaseAmountLogBO.setShopId(purchaseOrder.getShopId());
        purchaseAmountLogBO.setSupplierId(purchaseOrder.getSupplierId());
        purchaseAmountLogBO.setPurchaseTotalAmount(BigDecimal.valueOf(purchaseOrder.getTotalAmount()).longValue());
        purchaseAmountLogBO.setChangeAmount(changeAmount);
        purchaseAmountLogBO.setPurchaseAmountType(purchaseAmountType);
        purchaseAmountLogBO.setProdCount(prodCount);
        return purchaseAmountLogBO;
    }

    /**
     * 排序采购商品（按同spu排序）
     * @param purchaseOrderItems 采购商品集合
     * @return
     */
    private List<PurchaseOrderItemDTO> sortPurchaseItem(List<PurchaseOrderItemDTO> purchaseOrderItems) {
        if (CollectionUtils.isEmpty(purchaseOrderItems)) {
            return new ArrayList<>();
        }
        // 按spuId分类
        Map<Long, List<PurchaseOrderItemDTO>> spuMap = purchaseOrderItems.stream().collect(Collectors.groupingBy(PurchaseOrderItemDTO::getSpuId));
        // 组成list并返回
        List<PurchaseOrderItemDTO> sortItems = new ArrayList<>(purchaseOrderItems.size());
        spuMap.values().forEach(sortItems::addAll);
        return sortItems;
    }

    /**
     * 检查仓库
     * @param warehouseId 仓库id
     * @param shopId 店铺id
     * @param sysType 系统类型
     */
    private WarehouseVO checkWarehouse(Long warehouseId,
                                       Long shopId,
                                       Integer sysType) {
        WarehouseVO warehouse = warehouseFeignClient.getWarehouseById(warehouseId);
        if (Objects.isNull(warehouse)) {
            throw new LuckException(String.format("仓库[%s]不存在", warehouseId));
        }
        if (Objects.equals(warehouse.getSysType(), com.tmerclub.cloud.api.auth.constant.SysTypeEnum.STATION.value())) {
            // 检查门店仓库
            if(Objects.equals(sysType, com.tmerclub.cloud.api.auth.constant.SysTypeEnum.SUPPLIER.value())) {
                throw new LuckException("供应商不存在门店");
            }
            StationVO station = stationService.getByStationId(warehouse.getShopId());
            if (!Objects.equals(station.getShopId(), shopId))  {
                throw new LuckException(String.format("门店[%s]非该店铺的门店", station.getStationId()));
            }
        } else if (!Objects.equals(shopId, warehouse.getShopId())
                || !Objects.equals(sysType, warehouse.getSysType())) {
            // 检查商家/供应商仓库
            throw new LuckException(String.format("仓库[%s]非该店铺的仓库", warehouseId));
        }
        return warehouse;
    }

    /**
     * 检查采购订单
     * @param purchaseOrderId 采购订单id
     * @param shopId 店铺id
     * @return
     */
    private PurchaseOrderVO checkPurchaseOrder(Long purchaseOrderId, Long shopId) {
        PurchaseOrderVO purchaseOrder = purchaseOrderMapper.info(purchaseOrderId, null, I18nMessage.getLang());
        if (Objects.isNull(purchaseOrder)) {
            throw new LuckException("采购订单不存在");
        }
        if (!Objects.equals(purchaseOrder.getShopId(), shopId)) {
            throw new LuckException(ResponseEnum.UNAUTHORIZED);
        }
        if (Objects.equals(purchaseOrder.getStatus(), PurchasesStatusEnum.VOIDED.value())) {
            throw new LuckException("采购订单已作废");
        }
        if (Objects.equals(purchaseOrder.getStatus(), PurchasesStatusEnum.COMPLETION.value())) {
            throw new LuckException("采购订单已完成");
        }
        return purchaseOrder;
    }

    /**
     * 构建库存流水VO集合
     * @param purchaseOrderDTO 采购订单dto
     * @return 库存流水VO集合
     */
    private StockBillLogVO buildStockBillLog(PurchaseOrderDTO purchaseOrderDTO,
                                             Long warehouseId,
                                             StockBillType stockBillType) {
        // 商品数据准备
        Set<Long> spuIds = new HashSet<>(Constant.INITIAL_CAPACITY);
        Set<Long> skuIds = new HashSet<>(Constant.INITIAL_CAPACITY);
        for (PurchaseOrderItemDTO purchaseOrderItemDTO : purchaseOrderDTO.getPurchaseOrderItemList()) {
            spuIds.add(purchaseOrderItemDTO.getSpuId());
            skuIds.add(purchaseOrderItemDTO.getSkuId());
        }
        List<SpuVO> spuVOList = spuFeignClient.listSpuBySpuIds(new ArrayList<>(spuIds)).getData();
        List<SkuVO> skuVOList = skuFeignClient.listBySkuIds(new ArrayList<>(skuIds));
        Map<Long, SpuVO> spuMap = spuVOList.stream().collect(Collectors.toMap(SpuVO::getSpuId, x -> x));
        Map<Long, SkuVO> skuMap = skuVOList.stream().collect(Collectors.toMap(SkuVO::getSkuId, x -> x));
        // 构建库存流水日志
        StockBillLogVO stockBillLog = new StockBillLogVO();
        stockBillLog.setSourceOrderNo(purchaseOrderDTO.getPurchaseOrderId().toString());
        stockBillLog.setStockBillType(stockBillType.value());
        stockBillLog.setBusinessTime(new Date());
        stockBillLog.setRemark(purchaseOrderDTO.getRemark());
        if (Objects.equals(purchaseOrderDTO.getSysType(), SysTypeEnum.MULTISHOP.value())) {
            stockBillLog.setShopId(purchaseOrderDTO.getShopId());
            stockBillLog.setStockPointType(purchaseOrderDTO.getStockPointType());
        } else {
            stockBillLog.setSupplierId(purchaseOrderDTO.getSupplierId());
            stockBillLog.setStockPointType(StockPointType.WAREHOUSE.getValue());
        }
        stockBillLog.setEmployeeId(purchaseOrderDTO.getEmployeeId());
        stockBillLog.setType(Objects.equals(stockBillType, StockBillType.PURCHASE_OUTBOUND) ? StockType.OUT_OF_STOCK.value() : StockType.WAREHOUSING.value());
        stockBillLog.setStatus(StockBillStatus.SUCCESS.value());
        stockBillLog.setStockPointId(warehouseId);
        long totalAmount = 0L;
        int totalCount = 0;
        List<StockBillLogItemVO> stockBillLogItems = new ArrayList<>(Constant.INITIAL_CAPACITY);
        StockBillLogItemVO stockBillLogItem;
        for (PurchaseOrderItemDTO purchaseOrderItemDTO : purchaseOrderDTO.getPurchaseOrderItemList()) {
            stockBillLogItem = this.buildStockBillLogItem(purchaseOrderItemDTO, spuMap, skuMap);
            stockBillLogItems.add(stockBillLogItem);
            totalCount += stockBillLogItem.getStockCount();
            totalAmount += stockBillLogItem.getStockCount() * stockBillLogItem.getUnitPrice();
        }
        stockBillLog.setTotalAmount(totalAmount);
        stockBillLog.setTotalCount(totalCount);
        stockBillLog.setStockBillLogItems(stockBillLogItems);
        return stockBillLog;
    }

    /**
     * 构建库存流水项VO
     * @param purchaseOrderItemDTO 采购订单项dto
     * @param spuMap 商品spuMap
     * @param skuMap 商品skuMap
     * @return 库存流水项VO
     */
    private StockBillLogItemVO buildStockBillLogItem(PurchaseOrderItemDTO purchaseOrderItemDTO,
                                                     Map<Long, SpuVO> spuMap,
                                                     Map<Long, SkuVO> skuMap) {
        SkuVO skuVO = skuMap.get(purchaseOrderItemDTO.getSkuId());
        SpuVO spuVO = spuMap.get(purchaseOrderItemDTO.getSpuId());
        StockBillLogItemVO stockBillLogItem = new StockBillLogItemVO();
        stockBillLogItem.setStockCount(purchaseOrderItemDTO.getInboundStock());
        stockBillLogItem.setSpuId(spuVO.getSpuId());
        stockBillLogItem.setSkuId(skuVO.getSkuId());
        stockBillLogItem.setSpuName(spuVO.getName());
        stockBillLogItem.setSkuName(skuVO.getSkuName());
        stockBillLogItem.setPartyCode(skuVO.getPartyCode());
        stockBillLogItem.setMainImgUrl(spuVO.getMainImgUrl());
        stockBillLogItem.setImgUrl(skuVO.getImgUrl());
        stockBillLogItem.setUnitPrice(skuVO.getPriceFee());
        return stockBillLogItem;
    }

    /**
     * 构建sku库存VO
     * @param purchaseOrderItemDTO 采购订单项dto
     * @param warehouseId 仓库id
     * @param luaOperateEnum lua库存脚本操作
     * @return sku库存VO
     */
    private SkuStockVO buildSkuStockVO(PurchaseOrderItemDTO purchaseOrderItemDTO,
                                       Long warehouseId,
                                       LuaOperateEnum luaOperateEnum) {
        SkuStockVO skuStockVO = new SkuStockVO();
        BeanUtils.copyProperties(purchaseOrderItemDTO, skuStockVO);
        skuStockVO.setStockPointId(warehouseId);
        skuStockVO.setStock(purchaseOrderItemDTO.getInboundStock());
        skuStockVO.setOperateType(luaOperateEnum.value());
        return skuStockVO;
    }

    /**
     * 构建商家代销采购订单项集合
     * @param shopId 店铺id
     * @param purchaseOrderItems 采购订单项集合
     * @return 商家代销采购订单项集合
     */
    private List<PurchaseOrderItemDTO> buildSalePurchaseOrderItem(Long shopId,
                                                                  List<PurchaseOrderItemVO> purchaseOrderItems) {
        // 查询商家代销商品信息
        List<Long> supplierSpuIds = purchaseOrderItems.stream().map(PurchaseOrderItemVO::getSpuId).collect(Collectors.toList());
        List<SpuVO> spuVOList = spuFeignClient.listShopSpuBySupplierSpuIds(shopId, supplierSpuIds);
        Map<Long, SpuVO> spuMap = spuVOList.stream().collect(Collectors.toMap(SpuVO::getSupplierSpuId, s -> s));
        List<Long> spuIds = spuVOList.stream().map(SpuVO::getSpuId).toList();
        List<SkuVO> skuVOList = skuFeignClient.listBySpuIds(spuIds);
        Map<Long, SkuVO> skuMap = skuVOList.stream().collect(Collectors.toMap(SkuVO::getSupplierSkuId, s -> s));
        // 将采购订单项中的spu和sku换成商家的，方便后续对商家数据进行处理
        List<PurchaseOrderItemDTO> saleItems = new ArrayList<>(purchaseOrderItems.size());
        PurchaseOrderItemDTO saleItem;
        SpuVO spuVO;
        SkuVO skuVO;
        for (PurchaseOrderItemVO purchaseOrderItem : purchaseOrderItems) {
            spuVO = spuMap.get(purchaseOrderItem.getSpuId());
            skuVO = skuMap.get(purchaseOrderItem.getSkuId());
            saleItem = new PurchaseOrderItemDTO();
            BeanUtils.copyProperties(purchaseOrderItem, saleItem);
            saleItem.setSpuId(spuVO.getSpuId());
            saleItem.setSkuId(skuVO.getSkuId());
            saleItem.setSupplierSkuId(skuVO.getSupplierSkuId());
            saleItems.add(saleItem);
        }
        return saleItems;
    }

    private PurchaseOrderAddr getAndSavePurchaseOrderAddr(PurchaseOrderDTO purchaseOrderDTO, WarehouseVO warehouseVO) {
        PurchaseOrderAddr purchaseOrderAddr = BeanUtil.map(warehouseVO, PurchaseOrderAddr.class);
        purchaseOrderAddr.setPurchaseOrderAddrId(purchaseOrderDTO.getAddrId());
        // 仓库收货人是仓库管理者，门店收货人是门店名称
        purchaseOrderAddr.setConsignee(Objects.equals(warehouseVO.getSysType(), SysTypeEnum.STATION.value()) ? warehouseVO.getWarehouseName() : warehouseVO.getManage());
        purchaseOrderAddr.setMobile(warehouseVO.getPhone());
        purchaseOrderAddr.setAddr(warehouseVO.getAddress());
        purchaseOrderAddr.setPurchaseOrderAddrId(purchaseOrderDTO.getAddrId());
        purchaseOrderAddrService.save(purchaseOrderAddr);
        return purchaseOrderAddr;
    }

    private void setPurchaseInfo(PurchaseOrderDTO purchaseOrderDTO, StringBuilder orderSpuNameCn, StringBuilder orderSpuNameEn, PurchaseOrderItem purchaseOrderItem, SpuVO spu, SkuVO sku) {
        purchaseOrderItem.setStatus(PurchasesStatusEnum.UNPAY.value());
        purchaseOrderItem.setActualStock(0);
        purchaseOrderItem.setSpuId(spu.getSpuId());
        purchaseOrderItem.setSkuId(sku.getSkuId());
        purchaseOrderItem.setSpuCode(spu.getSpuCode());
        purchaseOrderItem.setPartyCode(sku.getPartyCode());
        purchaseOrderItem.setPic(StrUtil.isNotBlank(sku.getImgUrl()) ? sku.getImgUrl() : spu.getMainImgUrl());
        purchaseOrderItem.setPurchaseOrderId(purchaseOrderDTO.getPurchaseOrderId());
        purchaseOrderItem.setPurchasePrice(sku.getPriceFee());
        purchaseOrderItem.setPurchaseAmount(sku.getPriceFee() * purchaseOrderItem.getPurchaseStock());
        purchaseOrderItem.setBeDeliveredNum(purchaseOrderItem.getPurchaseStock());
        purchaseOrderItem.setPurchaseOrderItemLangList(getOrderItemLangList(sku.getSkuLangList(), spu.getSpuLangList(), orderSpuNameCn, orderSpuNameEn));
    }

    private Map<Long, SpuAndSkuVO> getSpuAndSkuMap(PurchaseOrderDTO purchaseOrderDTO, List<SkuVO> skuList) {
        ServerResponseEntity<List<SpuAndSkuVO>> spuAndSkuResponse = spuFeignClient.listSpuAndSkuById(skuList, purchaseOrderDTO.getSupplierId());
        if (!spuAndSkuResponse.isSuccess()) {
            throw new LuckException(spuAndSkuResponse.getMsg());
        }
        List<SpuAndSkuVO> spuAndSkuList = spuAndSkuResponse.getData();
        Map<Long, SpuAndSkuVO> spuAndSkuMap = spuAndSkuList.stream().collect(Collectors.toMap(SpuAndSkuVO::getSkuId, spuAndSkuVO -> spuAndSkuVO));
        if (spuAndSkuList.size() == 0) {
            throw new LuckException("yami.purchased.prod.not.exist.or.disabled");
        }
        return spuAndSkuMap;
    }

    private static List<SkuVO> getSkuVOList(PurchaseOrderDTO purchaseOrderDTO) {
        List<SkuVO> skuList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (PurchaseOrderItemDTO purchaseOrderItem : purchaseOrderDTO.getPurchaseOrderItemList()) {
            SkuVO skuVO = new SkuVO();
            skuVO.setSkuId(purchaseOrderItem.getSkuId());
            skuVO.setSpuId(purchaseOrderItem.getSpuId());
            skuList.add(skuVO);
        }
        return skuList;
    }


    /**
     * 采购订单中商品未导入自动导入
     *
     * @param purchaseOrder
     */
    private void voluntarilyImportSupplierSpu(PurchaseOrderDTO purchaseOrder) {
        List<SpuVO> spuVOList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (PurchaseOrderItemDTO purchaseOrderItemDTO : purchaseOrder.getPurchaseOrderItemList()) {
            SpuVO spuVO = new SpuVO();
            spuVO.setShopId(purchaseOrder.getShopId());
            spuVO.setSupplierSpuId(purchaseOrderItemDTO.getSpuId());
            spuVOList.add(spuVO);
        }
        Integer sysType = AuthUserContext.get().getSysType();
        ServerResponseEntity<Void> voidServerResponseEntity = spuFeignClient.voluntarilyImportSupplierSpu(spuVOList, sysType,
                AuthUserContext.get().getUserId());
        if (!voidServerResponseEntity.isSuccess()) {
            throw new LuckException(voidServerResponseEntity.getMsg());
        }
    }

    /**
     * 获取订单项的国际化信息
     *
     * @param skuLangList    规格语言信息
     * @param spuLangList    商品语言信息
     * @param orderSpuNameCn
     * @param orderSpuNameCn
     * @return 订单项的国际化信息列表
     */
    private List<PurchaseOrderItemLang> getOrderItemLangList(List<SkuLangVO> skuLangList, List<SpuLangVO> spuLangList,
                                                             StringBuilder orderSpuNameCn, StringBuilder orderSpuNameEn) {
        List<PurchaseOrderItemLang> orderItemLangList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        Map<Integer, String> spuNameMap = spuLangList.stream()
                .filter(orderSpuLangVO -> StrUtil.isNotBlank(orderSpuLangVO.getSpuName()))
                .collect(Collectors.toMap(SpuLangVO::getLang, SpuLangVO::getSpuName));
        Map<Integer, String> skuNameMap = skuLangList.stream()
                .filter(orderSkuLangVO -> StrUtil.isNotBlank(orderSkuLangVO.getSkuName()))
                .collect(Collectors.toMap(SkuLangVO::getLang, SkuLangVO::getSkuName));

        for (LanguageEnum value : LanguageEnum.values()) {
            Integer lang = value.getLang();
            if (!spuNameMap.containsKey(lang) && !skuNameMap.containsKey(lang)) {
                continue;
            }
            PurchaseOrderItemLang orderItemLang = new PurchaseOrderItemLang();
            orderItemLang.setLang(value.getLang());
            orderItemLang.setSkuName(LangUtil.getLangValue(skuNameMap, lang));
            orderItemLang.setSpuName(LangUtil.getLangValue(spuNameMap, lang));
            orderItemLangList.add(orderItemLang);
            if (Objects.equals(value, LanguageEnum.LANGUAGE_ZH_CN)) {
                orderSpuNameCn.append(orderItemLang.getSpuName()).append(StrUtil.COMMA);
            } else {
                orderSpuNameEn.append(orderItemLang.getSpuName()).append(StrUtil.COMMA);
            }
        }
        return orderItemLangList;
    }

    /**
     * 库存回退，并新增供应商库存流水
     * @param purchaseOrderVO 采购订单VO
     */
    private void reductionStock(PurchaseOrderVO purchaseOrderVO) {
        if (CollUtil.isEmpty(purchaseOrderVO.getPurchaseOrderItemList())) {
            log.info("采购单商品为空，采购单id：{}", purchaseOrderVO.getPurchaseOrderId());
            return;
        }
        // 过滤出部分入库商品
        List<PurchaseOrderItemDTO> purchaseOrderItems = purchaseOrderVO.getPurchaseOrderItemList().stream()
                .filter(x -> x.getPurchaseStock() > x.getActualStock()).map(x -> {
                    PurchaseOrderItemDTO purchaseOrderItemDTO = new PurchaseOrderItemDTO();
                    BeanUtils.copyProperties(x, purchaseOrderItemDTO);
                    purchaseOrderItemDTO.setInboundStock(x.getPurchaseStock() - x.getActualStock());
                    return purchaseOrderItemDTO;
                }).toList();
        if (CollectionUtils.isEmpty(purchaseOrderItems)) {
            return;
        }
        // 修改库存
        List<SkuStockVO> skuStockVOList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (PurchaseOrderItemDTO purchaseOrderItemDTO : purchaseOrderItems) {
            skuStockVOList.add(this.buildSkuStockVO(purchaseOrderItemDTO, purchaseOrderVO.getSupplierWarehouseId(), LuaOperateEnum.SKU_ADD));
        }
        skuStockFeignClient.changeSkuStock(skuStockVOList);
        // 新增流水记录
        PurchaseOrderDTO purchaseOrderDTO = new PurchaseOrderDTO();
        BeanUtils.copyProperties(purchaseOrderVO, purchaseOrderDTO);
        purchaseOrderDTO.setPurchaseOrderItemList(purchaseOrderItems);
        purchaseOrderDTO.setSysType(SysTypeEnum.SUPPLIER.value());
        StockBillLogVO stockBillLog = this.buildStockBillLog(purchaseOrderDTO, purchaseOrderVO.getSupplierWarehouseId(), StockBillType.ORDER_CANCEL);
        TransactionSendResult transactionSendResult = stockBillLogPurchaseStorageTemplate.sendMessageInTransaction(RocketMqConstant.STOCK_BILL_LOG_PURCHASE_STORAGE_TOPIC, new GenericMessage<>(stockBillLog), stockBillLog);
        if (!Objects.equals(transactionSendResult.getLocalTransactionState(), LocalTransactionState.COMMIT_MESSAGE)) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
    }

    /**
     * 构建采购导入excel数据
     * @param skuVO skuVO
     * @param partyCodeMap excel导入文件数据映射
     * @param spuMap spuVO映射
     * @param saleMap 商家代销商品映射
     * @param stockMap 商品库存映射
     * @param warehouseSupplierMap 仓库供应商映射
     * @param inWarehouseId 入库仓库id
     * @param outWarehouseId 出库仓库id
     */
    private PurchaseSpuVO buildPurchaseImportExcel(SkuVO skuVO,
                                                   Map<String, Integer> partyCodeMap,
                                                   Map<Long, SpuVO> spuMap,
                                                   Map<Long, Long> saleMap,
                                                   Map<String, SkuStockVO> stockMap,
                                                   Map<Long, SupplierApiDetailVO> warehouseSupplierMap,
                                                   Long inWarehouseId,
                                                   Long outWarehouseId) {
        SpuVO spuVO = spuMap.get(skuVO.getSpuId());
        PurchaseSpuVO purchaseSpuVO = new PurchaseSpuVO();
        BeanUtils.copyProperties(skuVO, purchaseSpuVO);
        purchaseSpuVO.setSkuName(CollectionUtils.isEmpty(skuVO.getSkuLangList()) ? "" : skuVO.getSkuLangList().get(0).getSkuName());
        purchaseSpuVO.setName(spuVO.getSpuLangList().get(0).getSpuName());
        purchaseSpuVO.setMainImgUrl(spuVO.getMainImgUrl());
        purchaseSpuVO.setPurchaseStock(partyCodeMap.get(skuVO.getPartyCode()));
        SupplierApiDetailVO supplier = warehouseSupplierMap.get(outWarehouseId);
        purchaseSpuVO.setSupplierId(supplier.getSupplierId());
        purchaseSpuVO.setSupplierName(supplier.getSupplierName());
        SkuStockVO skuStockVO;
        purchaseSpuVO.setStock(Objects.isNull((skuStockVO = stockMap.get(saleMap.get(skuVO.getSkuId()) + "_" + inWarehouseId))) ? 0 : skuStockVO.getStock());
        purchaseSpuVO.setSupplierStock(Objects.isNull((skuStockVO = stockMap.get(skuVO.getSkuId() + "_" + outWarehouseId))) ? 0 : skuStockVO.getStock());
        // 更新采购数量（负数改为0，超出库存改为当前库存）
//        if (purchaseSpuVO.getPurchaseStock() < 0) {
//            purchaseSpuVO.setPurchaseStock(0);
//        } else if (purchaseSpuVO.getPurchaseStock() > purchaseSpuVO.getSupplierStock()) {
//            purchaseSpuVO.setPurchaseStock(purchaseSpuVO.getSupplierStock());
//        }
        return purchaseSpuVO;
    }
}
