package com.hys.app.service.erp.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hys.app.converter.erp.ProcurementContractProductConverter;
import com.hys.app.converter.erp.WarehouseEntryConverter;
import com.hys.app.converter.erp.WarehouseEntryProductConverter;
import com.hys.app.framework.context.user.AdminUserContext;
import com.hys.app.framework.database.WebPage;
import com.hys.app.framework.database.mybatisplus.base.BaseServiceImpl;
import com.hys.app.framework.exception.ServiceException;
import com.hys.app.framework.rabbitmq.MessageSender;
import com.hys.app.framework.rabbitmq.MqMessage;
import com.hys.app.framework.util.CurrencyUtil;
import com.hys.app.framework.util.JsonUtil;
import com.hys.app.framework.util.PageConvert;
import com.hys.app.mapper.erp.StockTransferMapper;
import com.hys.app.mapper.erp.WarehouseEntryMapper;
import com.hys.app.mapper.erp.WarehouseOutMapper;
import com.hys.app.mapper.goods.GoodsMapper;
import com.hys.app.model.base.SettingGroup;
import com.hys.app.model.base.rabbitmq.AmqpExchange;
import com.hys.app.model.erp.dos.*;
import com.hys.app.model.erp.dto.*;
import com.hys.app.model.erp.dto.message.WarehouseEntryAuditPassMessage;
import com.hys.app.model.erp.enums.*;
import com.hys.app.model.erp.vo.WarehouseEntryAllowable;
import com.hys.app.model.erp.vo.WarehouseEntryStatistics;
import com.hys.app.model.erp.vo.WarehouseEntryVO;
import com.hys.app.model.goods.dos.CategoryDO;
import com.hys.app.model.system.vo.SiteSetting;
import com.hys.app.service.base.service.SettingManager;
import com.hys.app.service.erp.*;
import com.hys.app.service.goods.CategoryManager;
import com.hys.app.util.ValidateUtil;
import lombok.AllArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.hys.app.framework.util.CollectionUtils.convertMap;

/**
 * 入库单业务层实现
 *
 * @author 张崧
 * @since 2023-12-05 11:25:07
 */
@Service
@AllArgsConstructor
public class WarehouseEntryManagerImpl extends BaseServiceImpl<WarehouseEntryMapper, WarehouseEntryDO> implements WarehouseEntryManager {
    private WarehouseEntryConverter converter;
    private WarehouseEntryProductConverter itemConverter;
    private GoodsMapper goodsMapper;
    private WarehouseEntryProductManager warehouseEntryProductManager;
    private WarehouseEntryBatchManager warehouseEntryBatchManager;
    private NoGenerateManager noGenerateManager;
    private ProcurementContractProductManager contractProductManager;
    private WarehouseManager warehouseManager;
    private WarehouseEntryMapper warehouseEntryMapper;
    private MessageSender messageSender;
    private SettingManager settingManager;
    private ProductManager productManager;
    private ProcurementContractProductConverter procurementContractProductConverter;
    private CategoryManager categoryManager;
    private FinanceItemManager financeItemManager;
    private ProductStockManager productStockManager;
    private OrderManager orderManager;
    private GoodsSnManager goodsSnManager;
    private ItemSnCodeManager itemSnCodeManager;
    private WarehouseOutMapper warehouseOutMapper;
    private StockTransferMapper stockTransferMapper;
    private OrderItemManager orderItemManager;


    @Override
    public WebPage<WarehouseEntryDO> list(WarehouseEntryQueryParams queryParams) {
        WebPage<WarehouseEntryDO> page = baseMapper.selectPage(queryParams);
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long add(WarehouseEntryDTO warehouseEntryDTO) {
        check(warehouseEntryDTO);
        // 保存入库单
        WarehouseEntryDO warehouseEntryDO = BeanUtil.copyProperties(warehouseEntryDTO, WarehouseEntryDO.class);
        warehouseEntryDO.setSn(noGenerateManager.generate(NoBusinessTypeEnum.WarehouseEntry));
        save(warehouseEntryDO);
        // 保存入库单商品明细
        List<WarehouseEntryProductDTO> productList1 = warehouseEntryDTO.getProductList();
        ArrayList<WarehouseEntryProductDO> productList = new ArrayList<>();
        for (WarehouseEntryProductDTO dto : productList1) {
            WarehouseEntryProductDO productDO = BeanUtil.copyProperties(dto, WarehouseEntryProductDO.class);
            productDO.setProductId(dto.getProductId());
            productDO.setWarehouseEntryId(warehouseEntryDO.getId());
            productList.add(productDO);
        }
        warehouseEntryProductManager.saveBatch(productList);
        //保存子表和序列号的关系
        warehouseEntryDTO.setId(warehouseEntryDO.getId());
        saveSnCode(warehouseEntryDTO.getId(), productList);

        //如果是入库就要增加库存
        if ("submit".equals(warehouseEntryDTO.getSaveOrSubmit())) {
            updateStock(warehouseEntryDTO, getById(warehouseEntryDO.getId()), productList);
        }
        return warehouseEntryDO.getId();
    }


    private void saveSnCode(Long entryHouseId, List<WarehouseEntryProductDO> productList) {
        List<ItemSnCodeDO> itemSnCodeDOS = new ArrayList<>();
        //如果有序列号，保存序列号和入库单的关系，更爱序列号的状态
        for (WarehouseEntryProductDO aDo : productList) {
            if (CollUtil.isNotEmpty(aDo.getSnCodeList())) {
                aDo.getSnCodeList().forEach(item -> {
                    item.setItemId(aDo.getId());
                    ItemSnCodeDO itemSnCodeDO = new ItemSnCodeDO();
                    itemSnCodeDO.setItemId(aDo.getId());
                    itemSnCodeDO.setEntryOutHouseId(entryHouseId);
                    itemSnCodeDO.setType("in");
                    itemSnCodeDO.setSnCodeId(item.getId());
                    itemSnCodeDOS.add(itemSnCodeDO);
                });
            }
        }
        //保存序列号和子表的关系
        itemSnCodeManager.saveBatch(itemSnCodeDOS);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(WarehouseEntryDTO warehouseEntryDTO,Long id) {
        WarehouseEntryDO warehouseEntryDO = ValidateUtil.getOne(baseMapper, WarehouseEntryDO::getId, id, "入库单");
        AdminUserContext.compareCompany(warehouseEntryDO.getCompanyId());
        check(warehouseEntryDTO);
        // 更新入库单
         BeanUtil.copyProperties(warehouseEntryDTO, warehouseEntryDO);
        updateById(warehouseEntryDO);
        warehouseEntryProductManager.deleteByWarehouseEntryIds(Collections.singletonList(warehouseEntryDTO.getId()));
        ArrayList<WarehouseEntryProductDO> productList = new ArrayList<>();
        for (WarehouseEntryProductDTO dto : warehouseEntryDTO.getProductList()) {
            WarehouseEntryProductDO productDO = BeanUtil.copyProperties(dto, WarehouseEntryProductDO.class);
            productDO.setProductId(dto.getProductId());
            productDO.setWarehouseEntryId(warehouseEntryDO.getId());
            productList.add(productDO);
        }
        warehouseEntryProductManager.saveBatch(productList);
        //保存子表和序列号的关系
        warehouseEntryDTO.setId(warehouseEntryDO.getId());
        saveSnCode(warehouseEntryDTO.getId(), productList);

        if ("submit".equals(warehouseEntryDTO.getSaveOrSubmit())) {
            updateStock(warehouseEntryDTO, getById(warehouseEntryDO.getId()), productList);
        }
    }

    private void updateStock(WarehouseEntryDTO warehouseEntryDTO, WarehouseEntryDO warehouseEntryDO, ArrayList<WarehouseEntryProductDO> productList) {
        if ("Y".equals(warehouseEntryDO.getHasSubmit())) {
            throw new ServiceException("数据已入库,请勿重复操作");
        }
        for (WarehouseEntryProductDO aDo : productList) {
            ProductDO manager = productManager.getById(aDo.getProductId());
            if (manager.getHaveSn()) {
                if (CollUtil.isEmpty(aDo.getSnCodeList())) {
                    throw new ServiceException(manager.getId() + ":有序列号的商品入库需要录入序列号");
                }
                if (aDo.getNum() != aDo.getSnCodeList().size()) {
                    throw new ServiceException(manager.getId() + ":入库的数量须和序列号的个数相等");
                }
            }
        }
        //如果是调拨单得先出库才能入库，入库完之后改变调拨单得状态
        if (WarehouseEntyrTypeEnum.TRANSFER_ENTRY.equals(warehouseEntryDO.getType())) {
            WarehouseOutDO outDO = warehouseOutMapper.selectOne(new LambdaQueryWrapper<WarehouseOutDO>().eq(WarehouseOutDO::getOrderIdList, warehouseEntryDO.getOrderId()).last("limit 1"));
            if ("N".equals(outDO.getHasSubmit())) {
                throw new ServiceException("商品还未调拨出库");
            }
            StockTransferDO aDo = stockTransferMapper.selectById(warehouseEntryDO.getOrderId());
            aDo.setStatus(TransferTypeEnum.HAS_TRANSFER);
            stockTransferMapper.updateById(aDo);
        }

        List<Long> collect = warehouseEntryDTO.getProductList().stream().map(WarehouseEntryProductDTO::getProductId).collect(Collectors.toList());
        List<ProductStockDO> stockDOList = productStockManager.list(new LambdaQueryWrapper<ProductStockDO>()
                .eq(ProductStockDO::getWarehouseId, warehouseEntryDTO.getWarehouseId()).in(ProductStockDO::getProductId, collect));
        List<StockDTO> arrayList = new ArrayList<>();
        for (ProductStockDO aDo : stockDOList) {
            WarehouseEntryProductDTO productDO = warehouseEntryDTO.getProductList().stream().filter(item -> item.getProductId().equals(aDo.getProductId())).findFirst().get();
            //增加可用库存实际库存
            StockDTO dto = new StockDTO();
            dto.setId(aDo.getId());
            dto.setNum(productDO.getNum());
            arrayList.add(dto);
        }
        productStockManager.updateActualStock(arrayList,null);
        if (WarehouseEntyrTypeEnum.HAIL_ENTRY.equals(warehouseEntryDTO.getType())) {
            arrayList.forEach(item ->item.setNum(-item.getNum()));
            productStockManager.updateTransitStock(arrayList);
        }
        //入库之后数据不能被操作
        warehouseEntryDO.setHasSubmit("Y");
        updateById(warehouseEntryDO);

        List<ItemSnCodeDO> list1 = itemSnCodeManager.list(new LambdaQueryWrapper<ItemSnCodeDO>().eq(ItemSnCodeDO::getEntryOutHouseId, warehouseEntryDO.getId()));
        if (CollUtil.isNotEmpty(list1)) {
            List<Long> collect1 = list1.stream().map(ItemSnCodeDO::getSnCodeId).collect(Collectors.toList());
            List<GoodsSnDO> list = goodsSnManager.list(new LambdaQueryWrapper<GoodsSnDO>().in(GoodsSnDO::getId, collect1));

            //更爱序列号状态
            for (GoodsSnDO aDo : list) {
                aDo.setStatus(SnCodeStatusEnum.IN_WAREHOUSE);
                aDo.setWarehouseId(warehouseEntryDTO.getWarehouseId());
                aDo.setEntryHouseId(warehouseEntryDO.getId());
            }
            goodsSnManager.updateBatchById(list);
        }
        //如果是租赁订单
        if (WarehouseEntyrTypeEnum.HAIL_ENTRY.equals(warehouseEntryDTO.getType())) {
            OrderDO aDo = orderManager.getById(warehouseEntryDTO.getOrderId());
            List<OrderItemDO> list = orderItemManager.list(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, aDo.getId()));

            List<WarehouseEntryDO> entryDOS = list(new LambdaQueryWrapper<WarehouseEntryDO>()
                    .eq(WarehouseEntryDO::getHasSubmit, "Y")
                    .eq(WarehouseEntryDO::getOrderId, aDo.getId())
                    .eq(WarehouseEntryDO::getType, WarehouseEntyrTypeEnum.HAIL_ENTRY));
            List<Long> collected = entryDOS.stream().map(WarehouseEntryDO::getId).collect(Collectors.toList());
            //todo 后面报失 租转买的商品须累加
            List<WarehouseEntryProductDO> doList = warehouseEntryProductManager.list(new LambdaQueryWrapper<WarehouseEntryProductDO>()
                    .in(WarehouseEntryProductDO::getWarehouseEntryId, collected));
            List<OrderItemDO> objects = new ArrayList<>();
            for (OrderItemDO itemDO : list) {
                Optional<WarehouseEntryProductDO> first = doList.stream().filter(item -> item.getScanOrderItemId().equals(itemDO.getId())).findFirst();
                if (first.isPresent()) {
                    if (first.get().getNum() == itemDO.getNum()) {
                        objects.add(itemDO);
                    }
                }
            }
            //如果入库单的所有详细累加起来等于订单的详细 则该订单改为已完成
            if (list.size() == objects.size()) {
                aDo.setStatus(SaleOrderStatusEnum.ORDER_END);
                orderManager.updateById(aDo);
            }
        }
    }

    @Override
    public WarehouseEntryVO getDetail(Long id) {
        WarehouseEntryDO warehouseEntryDO = getById(id);
        WarehouseEntryVO warehouseEntryVO = BeanUtil.copyProperties(warehouseEntryDO, WarehouseEntryVO.class);
        List<WarehouseEntryProductDO> productList = warehouseEntryProductManager.list(new LambdaQueryWrapper<WarehouseEntryProductDO>().eq(WarehouseEntryProductDO::getWarehouseEntryId, id));

        List<Long> collect = productList.stream().map(WarehouseEntryProductDO::getProductId).collect(Collectors.toList());
        //所有的商品信息
        List<ProductDO> productDOS = productManager.list(new LambdaQueryWrapper<ProductDO>().in(ProductDO::getId, collect));
        List<ProductStockDO> stockDOList = productStockManager.list(new LambdaQueryWrapper<ProductStockDO>()
                .eq(ProductStockDO::getWarehouseId, warehouseEntryVO.getWarehouseId()).in(ProductStockDO::getProductId, collect));
        for (WarehouseEntryProductDO productDO : productList) {
            ProductDO aDo = productDOS.stream().filter(item -> item.getId().equals(productDO.getProductId())).findFirst().get();
            productDO.setGoodsVO(goodsMapper.selectById(aDo.getGoodsId()));
            productDO.setProductVO(aDo);
            List<ItemSnCodeDO> list = itemSnCodeManager.list(new LambdaQueryWrapper<ItemSnCodeDO>().eq(ItemSnCodeDO::getItemId, productDO.getId()));
            if (CollUtil.isNotEmpty(list)) {
                List<Long> collected = list.stream().map(ItemSnCodeDO::getSnCodeId).collect(Collectors.toList());
                productDO.setSnCodeList(goodsSnManager.list(new LambdaQueryWrapper<GoodsSnDO>().in(GoodsSnDO::getId, collected)));
            }
            productDO.setUsableStock(stockDOList.stream().filter(item -> item.getProductId().equals(productDO.getProductId())).findFirst().get().getUsableStock());
        }
        warehouseEntryVO.setProductList(itemConverter.convert(productList));
        return warehouseEntryVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        WarehouseEntryDO warehouseEntryDO = ValidateUtil.getOne(baseMapper, WarehouseEntryDO::getId, id, "入库单");
        AdminUserContext.compareCompany(warehouseEntryDO.getCompanyId());
        if ("Y".equals(warehouseEntryDO.getHasSubmit())) {
            throw new ServiceException("该数据已提交，不能删除");
        }
        removeById(id);
        // 删除明细
        warehouseEntryProductManager.remove(new LambdaQueryWrapper<WarehouseEntryProductDO>().eq(WarehouseEntryProductDO::getWarehouseEntryId, id));
    }

    @Override
    public void submit(List<Long> ids) {
        // 校验
        List<WarehouseEntryDO> list = listByIds(ids);
        for (WarehouseEntryDO warehouseEntryDO : list) {
            if (!new WarehouseEntryAllowable(warehouseEntryDO).getSubmit()) {
                throw new ServiceException(warehouseEntryDO.getSn() + "当前状态不允许提交");
            }
        }

        lambdaUpdate()
                .set(WarehouseEntryDO::getStatus, WarehouseEntryStatusEnum.Submit)
                .in(WarehouseEntryDO::getId, ids)
                .update();
    }

    @Override
    public void withdraw(Long id) {
        // 校验
        WarehouseEntryDO oldDO = getById(id);
        if (!new WarehouseEntryAllowable(oldDO).getWithdraw()) {
            throw new ServiceException("当前状态不允许撤销");
        }

        lambdaUpdate()
                .set(WarehouseEntryDO::getStatus, WarehouseEntryStatusEnum.NotSubmit)
                .eq(WarehouseEntryDO::getId, id)
                .update();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void audit(List<Long> ids, WarehouseEntryStatusEnum status, String remark) {
        if (status != WarehouseEntryStatusEnum.AuditPass && status != WarehouseEntryStatusEnum.AuditReject) {
            throw new ServiceException("审核参数错误");
        }

        List<WarehouseEntryDO> warehouseEntryList = listByIds(ids);
        for (WarehouseEntryDO warehouseEntryDO : warehouseEntryList) {
            // 校验
            if (!new WarehouseEntryAllowable(warehouseEntryDO).getAudit()) {
                throw new ServiceException(warehouseEntryDO.getSn() + "不能进行审核操作");
            }
        }

        lambdaUpdate()
                // 如果是驳回,状态改为未提交状态
                .set(WarehouseEntryDO::getStatus, status == WarehouseEntryStatusEnum.AuditReject ? WarehouseEntryStatusEnum.NotSubmit : status)
                .set(WarehouseEntryDO::getAuditRemark, remark)
                .set(WarehouseEntryDO::getAuditBy, AdminUserContext.getAdminUserName())
                .in(WarehouseEntryDO::getId, ids)
                .update();

        // 如果审核通过
        if (status == WarehouseEntryStatusEnum.AuditPass) {
            for (WarehouseEntryDO warehouseEntryDO : warehouseEntryList) {
                List<WarehouseEntryProductDO> productList = warehouseEntryProductManager.listByWarehouseEntryId(warehouseEntryDO.getId());
                // 更新合同明细的已入库数量
                contractProductManager.updateStockNum(warehouseEntryDO.getContractId(), productList);

                // 创建入库批次
                List<WarehouseEntryBatchDO> batchList = converter.combination(warehouseEntryDO, productList, noGenerateManager);
                warehouseEntryBatchManager.create(StockChangeSourceEnum.WAREHOUSE_ENTRY, warehouseEntryDO.getSn(), batchList);

                // 生成财务明细
                double totalPrice = CurrencyUtil.sum(productList, WarehouseEntryProductDO::getTotalPrice);
                financeItemManager.addExpand(FinanceExpandTypeEnum.Purchase, warehouseEntryDO.getSn(), totalPrice);
            }

            // 发送入库单审核通过消息
            WarehouseEntryAuditPassMessage message = new WarehouseEntryAuditPassMessage();
            message.setList(warehouseEntryList);
            this.messageSender.send(new MqMessage(AmqpExchange.WAREHOUSE_ENTRY_AUDIT_PASS, AmqpExchange.WAREHOUSE_ENTRY_AUDIT_PASS + "_ROUTING", message));
        }

    }

    @Override
    public void settlementComplete(Long supplierSettlementId, List<Long> ids) {
        lambdaUpdate()
                .set(WarehouseEntryDO::getSupplierSettlementFlag, true)
                .set(WarehouseEntryDO::getSupplierSettlementId, supplierSettlementId)
                .in(WarehouseEntryDO::getId, ids)
                .update();
    }

    @Override
    public void settlementCancel(Long supplierSettlementId) {
        lambdaUpdate()
                .set(WarehouseEntryDO::getSupplierSettlementFlag, false)
                .set(WarehouseEntryDO::getSupplierSettlementId, null)
                .eq(WarehouseEntryDO::getSupplierSettlementId, supplierSettlementId)
                .update();
    }

    /**
     * 查询入库单统计分页列表数据
     *
     * @param params 查询参数
     * @return
     */
    @Override
    public WebPage statistics(WarehouseEntryStatisticsParam params) {
        IPage<WarehouseEntryStatistics> iPage = this.warehouseEntryMapper.selectWarehouseEntryPage(new Page(params.getPageNo(), params.getPageSize()), params);
        return PageConvert.convert(iPage);
    }

    /**
     * 导出入库单统计列表数据
     *
     * @param response
     * @param params   查询参数
     */
    @Override
    public void export(HttpServletResponse response, WarehouseEntryStatisticsParam params) {
        //查询出库单商品列表
        List<WarehouseEntryStatistics> list = this.warehouseEntryMapper.selectWarehouseEntryList(params);

        ArrayList<Map<String, Object>> rows = CollUtil.newArrayList();
        ExcelWriter writer = ExcelUtil.getWriter(true);
        for (WarehouseEntryStatistics statistics : list) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("所属部门", statistics.getDeptName());
            map.put("仓库名称", statistics.getWarehouseName());
            map.put("供应商", statistics.getSupplierName());
            map.put("入库单编号", statistics.getEntrySn());
            map.put("商品编号", statistics.getSn());
            map.put("商品名称", statistics.getName());
            map.put("商品类别", statistics.getCategoryName());
            map.put("规格型号", statistics.getSpecification());
            map.put("单位", statistics.getUnit());
            map.put("入库数量", statistics.getNum());
            rows.add(map);
        }

        writer.write(rows, true);

        ServletOutputStream out = null;
        try {
            out = response.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=warehouse_entry.xlsx");
        writer.flush(out, true);
        writer.close();
        IoUtil.close(out);
    }

    /**
     * 判断合同是否已被入库单占用
     *
     * @param contractIds 合同ID集合
     * @return
     */
    @Override
    public boolean checkContractIsUsed(List<String> contractIds) {
        long count = this.lambdaQuery().in(WarehouseEntryDO::getContractId, contractIds).count();
        if (count > 0) {
            return true;
        }
        return false;
    }

    /**
     * 判断采购计划是否已被入库单占用
     *
     * @param planIds 采购计划ID集合
     * @return
     */
    @Override
    public boolean checkPlanIsUsed(List<Long> planIds) {
        long count = this.lambdaQuery().in(WarehouseEntryDO::getPurchasePlanId, planIds).count();
        if (count > 0) {
            return true;
        }
        return false;
    }

    @Override
    public long countByWarehouseId(Long warehouseId) {
        return lambdaQuery().eq(WarehouseEntryDO::getWarehouseId, warehouseId).count();
    }

    private void check(WarehouseEntryDTO warehouseEntryDTO) {
        if (WarehouseEntyrTypeEnum.HAIL_ENTRY.equals(warehouseEntryDTO.getType())) {
            if (ObjectUtil.isNull(warehouseEntryDTO.getOrderId())) {
                throw new ServiceException("租赁返回:订单不能为空");
            }
            OrderDO aDo = orderManager.getById(warehouseEntryDTO.getOrderId());
            if (ObjectUtil.isNull(aDo)) {
                throw new ServiceException("订单不存在");
            }
            if (!OrderTypeEnum.TO_C.equals(aDo.getType())) {
                throw new ServiceException("该订单不是租赁订单");
            }
            List<OrderItemDO> list = orderItemManager.list(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, warehouseEntryDTO.getOrderId()));
            List<OrderItemDO> objects = new ArrayList<>();
            warehouseEntryDTO.getProductList().forEach(item -> {
                if (ObjectUtil.isNull(item.getScanOrderItemId())) {
                    throw new ServiceException("租赁订单返回的商品必须在租赁订单里面");
                }
                Optional<OrderItemDO> first = list.stream().filter(it -> it.getId().equals(item.getScanOrderItemId())).findFirst();
                if (!first.isPresent()) {
                    throw new ServiceException("租赁订单返回的商品必须在租赁订单里面");
                }
                OrderItemDO orderItemDO = first.get();
                orderItemDO.setHasReturn(true);
                objects.add(orderItemDO);
            });
            //更改订单详情的是否返回 统计在途库存会用到
            orderItemManager.updateBatchById(objects);
        }

        //如果是售后订单
        if (WarehouseEntyrTypeEnum.SALE_AFTER.equals(warehouseEntryDTO.getType())) {
            if (ObjectUtil.isNull(warehouseEntryDTO.getOrderId())) {
                throw new ServiceException("售后退货:订单不能为空");
            }
            OrderDO aDo = orderManager.getById(warehouseEntryDTO.getOrderId());
            if (ObjectUtil.isNull(aDo)) {
                throw new ServiceException("订单不存在");
            }
            if (!SaleOrderStatusEnum.SALE_AFTER_ING.equals(aDo.getStatus()) &&
                    !SaleOrderStatusEnum.SALE_AFTER_END.equals(aDo.getStatus()) &&
                    !SaleOrderStatusEnum.SALE_AFTER_CANCEL.equals(aDo.getStatus()) ) {
                throw new ServiceException("未发现该订单有退货记录");
            }
            List<OrderItemDO> list = orderItemManager.list(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, warehouseEntryDTO.getOrderId()));
            List<OrderItemDO> objects = new ArrayList<>();
            warehouseEntryDTO.getProductList().forEach(item -> {
                if (ObjectUtil.isNull(item.getScanOrderItemId())) {
                    throw new ServiceException("退货商品返回的商品必须在租赁订单里面");
                }
                Optional<OrderItemDO> first = list.stream().filter(it -> it.getId().equals(item.getScanOrderItemId())).findFirst();
                if (!first.isPresent()) {
                    throw new ServiceException("退货商品返回的商品必须在租赁订单里面");
                }
                OrderItemDO orderItemDO = first.get();
                int allReturnNum= item.getNum()+orderItemDO.getHasReturnNum();
             if (allReturnNum>orderItemDO.getReturnNum()){
                 throw new ServiceException("退货数量不能大于脱货订单的数量");
             }
                orderItemDO.setHasReturnNum(item.getNum()+orderItemDO.getHasReturnNum());
                objects.add(orderItemDO);
            });
            //更改订单详情的是否返回 统计在途库存会用到
            orderItemManager.updateBatchById(objects);
        }

        WarehouseDO warehouseDO = warehouseManager.getById(warehouseEntryDTO.getWarehouseId());
        if (warehouseDO == null) {
            throw new ServiceException("仓库不存在");
        }

        for (WarehouseEntryProductDTO dto : warehouseEntryDTO.getProductList()) {
            ProductDO productDO = productManager.getById(dto.getProductId());
            if (CollUtil.isNotEmpty(dto.getSnCodeList())) {
                List<GoodsSnDO> list = goodsSnManager.list(new LambdaQueryWrapper<GoodsSnDO>()
                        .eq(GoodsSnDO::getProductId, dto.getProductId()).in(GoodsSnDO::getSnCode, dto.getSnCodeList().stream().map(GoodsSnDO::getSnCode).collect(Collectors.toList())));
                if (list.size() != dto.getSnCodeList().size()) {
                    throw new ServiceException(productDO.getSku() + "的部分序列号未查询到，请录入正确的序列号");
                }
            }
        }
    }

    private Double getPriceRatio() {
        String s = settingManager.get(SettingGroup.SITE);
        SiteSetting siteSetting = JsonUtil.jsonToObject(s, SiteSetting.class);
        Double priceRatio = siteSetting.getPriceRatio();
        if (priceRatio == null) {
            throw new ServiceException("进货价系数未设置，请先设置");
        }
        return priceRatio;
    }

}

