package com.sw.mes.store.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sw.mes.core.api.system.StoreFeignClients;
import com.sw.mes.core.api.system.YbFeignClients;
import com.sw.mes.core.context.BaseContextHandler;
import com.sw.mes.core.dto.WarehouseModelDto;
import com.sw.mes.core.enums.InputBillTypeEnum;
import com.sw.mes.core.exception.BusinessException;
import com.sw.mes.core.response.Result;
import com.sw.mes.core.response.ResultGenerator;
import com.sw.mes.core.utils.BeanUtil;
import com.sw.mes.core.utils.RedisTools;
import com.sw.mes.redis.server.RedissonUtils;
import com.sw.mes.store.api.interfaces.consumer.WarehouseConsumerService;
import com.sw.mes.store.constants.WarehouseConstant;
import com.sw.mes.store.dto.WarehouseAllotBillDetailDto;
import com.sw.mes.store.dto.WarehouseAllotBillDto;
import com.sw.mes.store.entity.*;
import com.sw.mes.store.enums.*;
import com.sw.mes.store.mapper.WarehouseAllotBillMapper;
import com.sw.mes.store.service.*;
import com.sw.mes.store.utils.CodeGenUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.modelmapper.ModelMapper;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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


/**
 * @Author
 * @Description：
 * @Date: Create in
 * @Modified By:
 */
@Service
public class WarehouseAllotBillServiceImpl extends ServiceImpl<WarehouseAllotBillMapper, WarehouseAllotBill> implements WarehouseAllotBillService {

    @Autowired
    private ModelMapper modelMapper;

    @Autowired
    private WarehouseInventoryService inventoryService;

    @Autowired
    private WarehouseMaterialService materialService;

    @Autowired
    private WarehouseAllotBillDetailService allotBillDetailService;

    @Autowired
    private WarehouseAllotBillService allotBillService;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private StoreFeignClients storeFeignClients;

    @Autowired
    private WarehouseInputRecordBillService inputRecordBillService;

    @Autowired
    private WarehouseInputRecordBillDetailService inputRecordBillDetailService;

    @Autowired
    private WarehouseOutputRecordBillService outputRecordBillService;

    @Autowired
    private WarehouseOutputRecordBillDetailService outputRecordBillDetailService;

    @Autowired
    private WarehouseAllotRecordBillService warehouseAllotRecordBillService;

    @Autowired
    private WarehouseAllotRecordBillDetailService warehouseAllotRecordBillDetailService;

    @Autowired
    private WarehouseModelService warehouseModelService;

    @Autowired
    private WarehouseConsumerService warehouseConsumerService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(WarehouseAllotBillDto warehouseAllotBillDto) {
        List<WarehouseAllotBillDetailDto> details = warehouseAllotBillDto.getAllotBillDetailDtos();
        if (CollectionUtils.isEmpty(details)) {
            throw new BusinessException("调拨明细为空，请检查数据！");
        }
        //调拨单号
        String billNo = StringUtils.isNotBlank(warehouseAllotBillDto.getBillNo()) ? warehouseAllotBillDto.getBillNo() : CodeGenUtil.genAllotBillNo();
        WarehouseAllotBill allotBill = this.getByBillNo(billNo);
        if (allotBill != null) {
            throw new BusinessException("调拨单号已存在，请检查数据！");
        }
        WarehouseAllotBill allotBills = new WarehouseAllotBill();
        BeanUtils.copyProperties(warehouseAllotBillDto, allotBills, "id");
        allotBills.setBillNo(billNo);
        if (StringUtils.isEmpty(allotBills.getAllotType())) {
            allotBills.setAllotType(AllotBillTypeEnum.手动新建.getValue());
        }
        if (ObjectUtils.isEmpty(allotBills.getCreateTime())) {
            allotBills.setCreateTime(new Date());
        }
        if (ObjectUtils.isEmpty(allotBills.getCreateUserName())) {
            allotBills.setCreateUserName(BaseContextHandler.getUsername());
        }
        if (ObjectUtils.isEmpty(allotBills.getCreateUserId())) {
            allotBills.setCreateUserId(BaseContextHandler.getUserID());
        }
        allotBills.setStatus(AllotBillStatusEnum.待审核.getValue());
        //保存入库单
        this.saveOrUpdate(allotBills);
        //保存调拨单记录
//        WarehouseAllotRecordBill recordBill = new WarehouseAllotRecordBill();
//        List<WarehouseAllotRecordBillDetail> allotRecordBillDetails = new ArrayList<>();
//        BeanUtils.copyProperties(allotBills, recordBill, "id");
//        recordBill.setAllotBillNo(allotBills.getBillNo());
//        recordBill.setAllotBillId(allotBills.getId());
//        recordBill.setRecordBillNo(allotBills.getBillNo());
//        warehouseAllotRecordBillService.save(recordBill);
        List<WarehouseAllotBillDetail> detaiList = new ArrayList<>(details.size());
        //当开启了唯一码，用于判断是否存在相同的唯一码
        Set<String> uniqueCodeSet = new HashSet<>();
        for (WarehouseAllotBillDetailDto allotBillDetail : details) {
            String uniqueCode = allotBillDetail.getUniqueCode();
            if (StringUtils.isNotBlank(uniqueCode)) {
                //校验调拨明细中唯一码是否重复
                boolean add = uniqueCodeSet.add(uniqueCode);
                //查询是否已存在重复唯一码
                if (!add) {
                    throw new BusinessException("唯一码【" + uniqueCode + "】重复，请检查数据重新输入！");
                } else {
                    BigDecimal count = allotBillDetail.getCount();
                    //唯一码物料库存只能是 1
                    if (count.compareTo(new BigDecimal(1)) != 0) {
                        throw new BusinessException("唯一码【" + uniqueCode + "】物料调拨数量只能为1，请检查数据重新输入！");
                    }
                }
            }
            if (null != allotBillDetail.getAllotWarehouseId()) {
                WarehouseModel warehouseModel = warehouseModelService.getById(allotBillDetail.getAllotWarehouseId());
                if (!ObjectUtils.isEmpty(warehouseModel)) {
                    allotBillDetail.setAllotWarehouseId(warehouseModel.getId());
                    allotBillDetail.setAllotWarehouseCode(warehouseModel.getCode());
                    allotBillDetail.setAllotWarehouseName(warehouseModel.getName());
                } else {
                    throw new RuntimeException("未查询到对应的库位信息");
                }
            } else {
                if (StringUtils.isNotBlank(allotBillDetail.getAllotWarehouseCode())) {
                    WarehouseModel warehouseModel = warehouseModelService.findByCode(allotBillDetail.getAllotWarehouseCode());
                    if (!ObjectUtils.isEmpty(warehouseModel)) {
                        allotBillDetail.setAllotWarehouseId(warehouseModel.getId());
                        allotBillDetail.setAllotWarehouseCode(warehouseModel.getCode());
                        allotBillDetail.setAllotWarehouseName(warehouseModel.getName());
                    }
                } else {
                    throw new RuntimeException("未查询到对应的库位信息");
                }
            }
            if (null != allotBillDetail.getWarehouseId()) {
                WarehouseModel warehouseModel = warehouseModelService.getById(allotBillDetail.getAllotWarehouseId());
                if (!ObjectUtils.isEmpty(warehouseModel)) {
                    allotBillDetail.setAllotWarehouseId(warehouseModel.getId());
                    allotBillDetail.setAllotWarehouseCode(warehouseModel.getCode());
                    allotBillDetail.setAllotWarehouseName(warehouseModel.getName());
                } else {
                    throw new RuntimeException("未查询到对应的库位信息");
                }
            } else {
                if (StringUtils.isNotBlank(allotBillDetail.getWarehouseCode())) {
                    WarehouseModel warehouseModel = warehouseModelService.findByCode(allotBillDetail.getWarehouseCode());
                    if (!ObjectUtils.isEmpty(warehouseModel)) {
                        allotBillDetail.setAllotWarehouseId(warehouseModel.getId());
                        allotBillDetail.setAllotWarehouseCode(warehouseModel.getCode());
                        allotBillDetail.setAllotWarehouseName(warehouseModel.getName());
                    }
                } else {
                    throw new RuntimeException("未查询到对应的库位信息");
                }
            }
            WarehouseAllotBillDetail detail = new WarehouseAllotBillDetail();
            BeanUtils.copyProperties(allotBillDetail, detail, "id");
            detail.setRemark(allotBills.getRemark());
            detail.setStatus(AllotBillStatusEnum.待审核.getValue());
            detail.setAllotBillId(allotBills.getId());
            detail.setAllotBillNo(allotBills.getBillNo());
            if (ObjectUtils.isEmpty(warehouseAllotBillDto.getCreateTime())) {
                detail.setCreateTime(new Date());
            } else {
                detail.setCreateTime(warehouseAllotBillDto.getCreateTime());
            }
            if (ObjectUtils.isEmpty(warehouseAllotBillDto.getCreateUserName())) {
                detail.setCreateUserName(BaseContextHandler.getUsername());
            } else {
                detail.setCreateUserName(warehouseAllotBillDto.getCreateUserName());
            }
            if (ObjectUtils.isEmpty(warehouseAllotBillDto.getCreateUserId())) {
                detail.setCreateUserId(BaseContextHandler.getUserID());
            } else {
                detail.setCreateUserId(warehouseAllotBillDto.getCreateUserId());
            }
            if (ObjectUtils.isEmpty(warehouseAllotBillDto.getUpdateUserName())) {
                detail.setUpdateUserName(warehouseAllotBillDto.getCreateUserName());
            } else {
                detail.setUpdateUserName(warehouseAllotBillDto.getUpdateUserName());
            }
            if (ObjectUtils.isEmpty(warehouseAllotBillDto.getUpdateUserId())) {
                detail.setUpdateUserId(warehouseAllotBillDto.getCreateUserId());
            } else {
                detail.setUpdateUserId(warehouseAllotBillDto.getUpdateUserId());
            }
            detaiList.add(detail);
//            WarehouseAllotRecordBillDetail warehouseAllotRecordBillDetail = new WarehouseAllotRecordBillDetail();
//            BeanUtils.copyProperties(detail, warehouseAllotRecordBillDetail, "id");
//            warehouseAllotRecordBillDetail.setRecordBillId(recordBill.getId());
//            warehouseAllotRecordBillDetail.setRecordBillNo(recordBill.getRecordBillNo());
//            warehouseAllotRecordBillDetail.setAllotBillNo(detail.getAllotBillNo());
//            warehouseAllotRecordBillDetail.setAllotBillId(detail.getAllotBillId());
//            if (ObjectUtils.isEmpty(allotBills.getCreateTime())) {
//                warehouseAllotRecordBillDetail.setCreateTime(new Date());
//            }
//            if (ObjectUtils.isEmpty(allotBills.getCreateUserName())) {
//                warehouseAllotRecordBillDetail.setCreateUserName(BaseContextHandler.getUsername());
//            }
//            if (ObjectUtils.isEmpty(allotBills.getCreateUserId())) {
//                warehouseAllotRecordBillDetail.setCreateUserId(BaseContextHandler.getUserID());
//            }
//            warehouseAllotRecordBillDetail.setMaterialModelId(Integer.valueOf(String.valueOf(detail.getMaterialModelId())));
//            allotRecordBillDetails.add(warehouseAllotRecordBillDetail);
        }
        allotBillDetailService.saveBatch(detaiList);
//        warehouseAllotRecordBillDetailService.saveBatch(allotRecordBillDetails);
        //如果是自动审核，直接入库
        if (allotBills.getAutoAudit()) {
            BeanUtil.copyBeanPropWithOutNullValue(warehouseAllotBillDto, allotBills);
            allotBillService.autoReceiveAtomic(warehouseAllotBillDto);
        }
    }

    /**
     * 调拨单审核，原子操作
     **/
    @Override
    public void auditReceiveAtomic(WarehouseAllotBillDto allotBillDto) {
        RLock lock = RedissonUtils.getRLock(redissonClient, WarehouseConstant.UPDATE_INVENTORY_LOCK_KEY);
        boolean isLock = RedissonUtils.getRLockExpireTime(lock, 6L, 6L);
        if (isLock) {
            try {
                lock.lock();
                allotBillService.auditReceive(allotBillDto);
            } finally {
                if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
        } else {
            throw new BusinessException("有其他人正在操作，请稍后再试！");
        }
    }

    /**
     * 调拨单审核
     **/
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void auditReceive(WarehouseAllotBillDto allotBillDto) {
        WarehouseAllotBill warehouseAllotBill = this.getByBillNo(allotBillDto.getBillNo());
        if (warehouseAllotBill == null) {
            throw new BusinessException("入库单号：" + allotBillDto.getBillNo() + "信息为空，请检查数据！");
        }
        String status = warehouseAllotBill.getStatus();
        if (!AllotBillStatusEnum.待审核.getValue().equals(status)) {
            throw new BusinessException("入库单号：" + allotBillDto.getBillNo() + "状态不是【" + AllotBillStatusEnum.待审核.getValue() + "】状态，审核失败！");
        }
        if (null != allotBillDto.getAllotWarehouseId()) {
            WarehouseModel warehouseModel = warehouseModelService.getById(allotBillDto.getAllotWarehouseId());
            if (ObjectUtils.isNotEmpty(warehouseModel)) {
                allotBillDto.setAllotWarehouseCode(warehouseModel.getCode());
            }
        }
        //更新库存
        this.updateInventory(allotBillDto);
        warehouseConsumerService.afterAuditAllot(allotBillDto);
    }

    /**
     * 调拨单审核无需审核，直接更新库存
     **/
    @Override
    public void autoReceiveAtomic(WarehouseAllotBillDto allotBillDto) {
//        RLock lock = RedissonUtils.getRLock(redissonClient, WarehouseConstant.UPDATE_INVENTORY_LOCK_KEY);
//        boolean isLock = RedissonUtils.getRLockExpireTime(lock, 6L, 6L);
//        if (isLock) {
//            try {
//                lock.lock();
//                allotBillService.autoReceive(allotBillDto);
//            } finally {
//                if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) {
//                    lock.unlock();
//                }
//            }
//        } else {
//            throw new BusinessException("有其他人正在操作，请稍后再试！");
//        }
        allotBillService.autoReceive(allotBillDto);
    }

    /**
     * 无需审核，直接更新库存
     **/
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void autoReceive(WarehouseAllotBillDto allotBillDto) {
        this.updateInventory(allotBillDto);
        warehouseConsumerService.afterAuditAllot(allotBillDto);
    }

    private void updateInventory(WarehouseAllotBillDto allotBillDto) {
        WarehouseAllotBill allotBill = modelMapper.map(allotBillDto, WarehouseAllotBill.class);
        //更新调拨单状态
        allotBill.setId(allotBillDto.getId());
        allotBill.setStatus(AllotBillStatusEnum.审核成功.getValue());
        allotBill.setUpdateTime(new Date());
        allotBill.setUpdateUserId(BaseContextHandler.getUserID());
        allotBill.setUpdateUserName(BaseContextHandler.getUsername());
        this.saveOrUpdate(allotBill);
        //生成出入库记录
        this.saveRecord(allotBill, AllotBillStatusEnum.审核成功);
        List<WarehouseAllotBillDetailDto> allotBillDetails = allotBillDto.getAllotBillDetailDtos();
        if (CollectionUtils.isEmpty(allotBillDetails)) {
            throw new BusinessException("入库单号【" + allotBillDto.getBillNo() + "】对应的入库明细为空，请检查数据！");
        }
        //更新入库明细状态
        this.updateDetail(allotBillDetails);
        for (WarehouseAllotBillDetailDto allotBillDetail : allotBillDetails) {
            //手动审核明细中没有传入库位编码
            if (StringUtils.isNotBlank(allotBillDto.getAllotWarehouseCode())) {
                allotBillDetail.setAllotWarehouseCode(allotBillDto.getAllotWarehouseCode());
            }
            //目标库位
            Long allotWarehouseId = allotBillDetail.getAllotWarehouseId();
            if ((allotWarehouseId == null || allotWarehouseId == 0) && StringUtils.isEmpty(allotBillDetail.getAllotWarehouseCode())) {
                throw new BusinessException("目标库位为空！");
            }
            if (null == allotWarehouseId && StringUtils.isEmpty(allotBillDetail.getAllotWarehouseCode())) {
                WarehouseModel warehouseModel = warehouseModelService.getCode(allotBillDetail.getAllotWarehouseCode());
                if (ObjectUtils.isNotEmpty(warehouseModel)) {
                    allotWarehouseId = warehouseModel.getId();
                }
            }

            //原库存数据ID
            Long inventoryId = allotBillDetail.getInventoryId();
            WarehouseInventory inventory = inventoryService.getById(inventoryId);
            List<WarehouseInventory> warehouseInventories = new ArrayList<>();
            if (null == inventory) {
                warehouseInventories = inventoryService.getByMaterialAndBatchNoAndWarehouseId(allotBillDto.getAllotBillDetailDtos().get(0).getBatchNo(),
                        allotBillDetail.getMaterialModelCode(), allotBillDto.getAllotBillDetailDtos().get(0).getWarehouseId());
                if (warehouseInventories.size() > 0) {
                    inventory = warehouseInventories.get(0);
                }
            }
            if (inventory == null || inventory.getDel()) {
                throw new BusinessException("原库存数据不存在或库存不足！");
            }
            //调拨数量
            BigDecimal count = allotBillDetail.getCount();
            if (count == null || count.compareTo(new BigDecimal("0")) == -1) {
                throw new BusinessException("调拨数量为空！");
            }
            String uniqueCode = allotBillDetail.getUniqueCode();
            String batchNo = allotBillDetail.getBatchNo();
            if (StringUtils.isNotBlank(uniqueCode)) {
                //更新原库位为已出库
                inventory.setDel(true);
                inventory.setQuantity(new BigDecimal("0"));
                inventoryService.saveOrUpdate(inventory);
                WarehouseInventory byUniqueCode = inventoryService.getByUniqueCode(uniqueCode);
                if (byUniqueCode != null) {
                    throw new BusinessException("已存在相同唯一码【" + uniqueCode + "】库存记录，请重新输入唯一码！");
                }
                BigDecimal uniqueCount = allotBillDetail.getCount();
                //唯一码物料库存只能是 1
                if (uniqueCount.compareTo(new BigDecimal(1)) == 1) {
                    throw new BusinessException("唯一码【" + uniqueCode + "】入库数量只能为1，请检查数据！");
                }
                //检查当前数据的唯一码是否是其他数据的批次号，不同数据 的唯一码和批次号都不能相同
                List<WarehouseInventory> byBatchNo = inventoryService.getByBatchNo(uniqueCode);
                if (CollectionUtils.isNotEmpty(byBatchNo)) {
                    throw new BusinessException("当前唯一码【" + uniqueCode + "】与已有的批次号重复，请检查数据！");
                }
                //新增一条库存数据
                WarehouseInventory inventoryNew = new WarehouseInventory();
                BeanUtil.copyBeanPropWithOutNullValue(inventoryNew, inventory);
                inventoryNew.setId(null);
                inventoryNew.setDel(false);
                inventoryNew.setQuantity(new BigDecimal("1"));
                inventoryNew.setWarehouseId(allotWarehouseId);
                inventoryNew.setWarehouseName(allotBillDetail.getAllotWarehouseName());
                inventoryNew.setReceiveTime(new Date());
                inventoryNew.setReceiveUserId(BaseContextHandler.getUserID());
                inventoryNew.setReceiveUserName(BaseContextHandler.getUsername());
                inventoryNew.setWarehouseCode(allotBillDetail.getAllotWarehouseCode());
                inventoryNew.setMaterialGear(allotBillDetail.getMaterialGear());
                inventoryNew.setSupplier(allotBillDetail.getSupplier());
                inventoryNew.setMaterialLevel(allotBillDetail.getMaterialLevel());
                inventoryService.saveOrUpdate(inventoryNew);
            } else {
                String materialModelCode = allotBillDetail.getMaterialModelCode();
                BigDecimal quantity = inventory.getQuantity();
                if (quantity == null || count.compareTo(quantity) > 0) {
                    throw new BusinessException("原库存料号【" + materialModelCode + "】库存量不足，无法调拨！");
                }
                //扣减原库位库存
                inventory.setQuantity(quantity.subtract(count));
                if (quantity.subtract(count).compareTo(new BigDecimal("0")) == 0) {
                    inventory.setDel(true);
                }
                inventoryService.updateInventory(inventory, 2);
                //增加目标库位库存
                List<WarehouseInventory> warehouseInventory;
                if (StringUtils.isNotBlank(batchNo)) {
                    //检查当前数据的批次号是否是其他数据的唯一码，不同数据 的唯一码和批次号都不能相同
                    WarehouseInventory byUniqueCode = inventoryService.getByUniqueCode(batchNo);
                    if (byUniqueCode != null) {
                        throw new BusinessException("当前批次号【" + batchNo + "】与已有的唯一码重复，请检查数据！");
                    }
                    warehouseInventory = inventoryService.getByMaterialAndBatchNoAndWarehouseId(batchNo, materialModelCode, allotWarehouseId);
                    warehouseInventory = warehouseInventory.stream().filter(e -> StringUtils.isBlank(e.getUniqueCode())).collect(Collectors.toList());
                } else {
                    //未开启唯一码和批次号，物料+库位判重
                    warehouseInventory = inventoryService.getByMaterialAndBatchNoAndWarehouseId(null, materialModelCode, allotWarehouseId);
                    warehouseInventory = warehouseInventory.stream().filter(e -> StringUtils.isBlank(e.getUniqueCode()) && StringUtils.isBlank(e.getBatchNo())).collect(Collectors.toList());
                }
                if (org.apache.commons.collections.CollectionUtils.isNotEmpty(warehouseInventory)) {
                    WarehouseInventory inventory1 = warehouseInventory.get(0);
                    inventory1.setQuantity(inventory1.getQuantity().add(count));
                    //更新库存
                    inventoryService.updateInventory(inventory1, 1);
                } else {
                    //新增库存
                    WarehouseModel warehouseModel = warehouseModelService.getCode(allotBillDetail.getAllotWarehouseCode());
                    if (!ObjectUtils.isEmpty(warehouseModel)) {
                        allotBillDetail.setAllotWarehouseId(warehouseModel.getId());
                        allotBillDetail.setAllotWarehouseName(warehouseModel.getName());
                        allotBillDetail.setAllotWarehouseCode(warehouseModel.getCode());
                    }
                    addInventory(allotBillDetail);
                }
            }
        }
    }

    @Override
    public WarehouseAllotBill getByBillNo(String billNo) {
        LambdaQueryWrapper<WarehouseAllotBill> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WarehouseAllotBill::getBillNo, billNo);
        List<WarehouseAllotBill> list = list(queryWrapper);
        if (CollectionUtils.isNotEmpty(list)) {
            return list.get(0);
        }
        return null;
    }

    /**
     * @return com.sw.common.core.response.Result
     * @Author wupeng
     * @Description 拒绝调拨
     * @Date 16:43 2023/11/21
     * @Param
     **/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result rejectApply(WarehouseAllotBillDto allotBillDto) {
        String billNo = allotBillDto.getBillNo();
        if (StringUtils.isBlank(billNo)) {
            return ResultGenerator.fail("单据号不能为空！");
        }
        WarehouseAllotBill allotBill = this.getByBillNo(billNo);
        if (allotBill == null) {
            return ResultGenerator.fail("该单据不存在！");
        }
        String status = allotBill.getStatus();
        if (!AllotBillStatusEnum.待审核.getValue().equals(status)) {
            return ResultGenerator.fail("该单据是【" + status + "】状态，无法拒绝审核！");
        }
        allotBill.setRejectReason(allotBillDto.getRejectReason());
        allotBill.setRejectReasonRemark(allotBillDto.getRejectReasonRemark());
        allotBill.setStatus(AllotBillStatusEnum.审核失败.getValue());
        allotBill.setUpdateUserName(BaseContextHandler.getUsername());
        allotBill.setUpdateTime(new Date());
        allotBill.setUpdateUserId(BaseContextHandler.getUserID());
        //更新调拨单状态
        this.saveOrUpdate(allotBill);
        //更新入库明细状态
        List<WarehouseAllotBillDetail> details = allotBillDetailService.getByBillNo(billNo);
        if (CollectionUtils.isEmpty(details)) {
            throw new BusinessException("该单据明细为空，取消失败！");
        }
        details.forEach(billDetail -> {
            billDetail.setStatus(AllotBillStatusEnum.审核失败.getValue());
            billDetail.setUpdateTime(new Date());
            billDetail.setUpdateUserId(BaseContextHandler.getUserID());
            billDetail.setUpdateUserName(BaseContextHandler.getUsername());
        });
        allotBillDetailService.saveOrUpdateBatch(details);
        return ResultGenerator.success();
    }

    private void addInventory(WarehouseAllotBillDetailDto allotBillDetailDto) {
        WarehouseInventory inventory = new WarehouseInventory();
        BeanUtils.copyProperties(allotBillDetailDto, inventory, "id");
        inventory.setMaterialModelId(allotBillDetailDto.getMaterialModelId());
        inventory.setMaterialModelCode(allotBillDetailDto.getMaterialModelCode());
        inventory.setMaterialModelName(allotBillDetailDto.getMaterialModelName());
        inventory.setMaterialTypeName(allotBillDetailDto.getMaterialTypeName());
        inventory.setMaterialCategoryName(allotBillDetailDto.getMaterialCategoryName());
        inventory.setUniqueCode(allotBillDetailDto.getUniqueCode());
        inventory.setBatchNo(allotBillDetailDto.getBatchNo());
        inventory.setSupplier(allotBillDetailDto.getSupplier());
        inventory.setSpecification(allotBillDetailDto.getSpecification());
        inventory.setMaterialTh(allotBillDetailDto.getMaterialTh());
        inventory.setQuantity(allotBillDetailDto.getCount());
        inventory.setUnitName(allotBillDetailDto.getUnitName());
        inventory.setWarehouseId(allotBillDetailDto.getAllotWarehouseId());
        inventory.setWarehouseName(allotBillDetailDto.getAllotWarehouseName());
        inventory.setReceiveTime(new Date());
        inventory.setReceiveUserId(BaseContextHandler.getUserID());
        inventory.setReceiveUserName(BaseContextHandler.getUsername());
        inventory.setMaterialXh(allotBillDetailDto.getMaterialTh());
        inventory.setWarehouseCode(allotBillDetailDto.getAllotWarehouseCode());
        inventory.setMaterialGear(allotBillDetailDto.getMaterialGear());
        inventory.setSupplier(allotBillDetailDto.getSupplier());
        inventory.setMaterialLevel(allotBillDetailDto.getMaterialLevel());
        //查询物料模型配置
        WarehouseMaterial warehouseMaterial = materialService.getByMaterialId(allotBillDetailDto.getMaterialModelId());
        if (warehouseMaterial != null) {
            inventory.setSafetyStock(warehouseMaterial.getLowerLimit() + "-" + warehouseMaterial.getUpperLimit());
            inventory.setResidenceTime(warehouseMaterial.getResidenceTime());
            inventory.setTimeUnit(warehouseMaterial.getTimeUnit());
        }
//        String lockKey = new String();
//        //唯一码存在
//        if (StringUtils.isNotBlank(inventory.getUniqueCode())) {
//            WarehouseModel warehouseModel = warehouseModelService.getById(inventory.getWarehouseId());
//            if (StringUtils.isNotBlank(warehouseModel.getCode())) {
//                lockKey = inventory.getMaterialModelCode() + warehouseModel.getCode() + inventory.getUniqueCode();
//            } else {
//                throw new BusinessException("未查询到【" + inventory.getWarehouseId() + "】库位信息!");
//            }
//        } else if (StringUtils.isEmpty(inventory.getUniqueCode()) && StringUtils.isNotBlank(inventory.getBatchNo())) {
//            //唯一码不存在,用批次号
//            WarehouseModel warehouseModel = warehouseModelService.getById(inventory.getWarehouseId());
//            if (StringUtils.isNotBlank(warehouseModel.getCode())) {
//                lockKey = inventory.getMaterialModelCode() + warehouseModel.getCode() + inventory.getBatchNo();
//            } else {
//                throw new BusinessException("未查询到【" + inventory.getWarehouseId() + "】库位信息!");
//            }
//        }else if(StringUtils.isEmpty(inventory.getUniqueCode()) && StringUtils.isEmpty(inventory.getBatchNo())){
//            WarehouseModel warehouseModel = warehouseModelService.getById(inventory.getWarehouseId());
//            if (StringUtils.isNotBlank(warehouseModel.getCode())) {
//                lockKey = inventory.getMaterialModelCode() + warehouseModel.getCode();
//            } else {
//                throw new BusinessException("未查询到【" + inventory.getWarehouseId() + "】库位信息!");
//            }
//        }
//        RLock lock = RedissonUtils.getRLock(redissonClient, lockKey);
//        boolean isLock = RedissonUtils.getRLockExpireTime(lock, 6L, 6L);
//        if (isLock) {
//            try {
//                lock.lock();
        inventoryService.save(inventory);
//            } finally {
//                if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) {
//                    lock.unlock();
//                    RedisTools.deleteObject(lockKey);
//                }
//            }
//        } else {
//            throw new BusinessException("有其他人正在操作，请稍后再试！");
//        }
    }

    private void updateDetail(List<WarehouseAllotBillDetailDto> billDetailDtos) {
        List<WarehouseAllotBillDetail> collect = billDetailDtos.stream().map(billDetailDto -> {
            WarehouseAllotBillDetail billDetail = modelMapper.map(billDetailDto, WarehouseAllotBillDetail.class);
            billDetail.setStatus(AllotBillStatusEnum.审核成功.getValue());
            billDetail.setUpdateTime(new Date());
            billDetail.setUpdateUserId(BaseContextHandler.getUserID());
            billDetail.setUpdateUserName(BaseContextHandler.getUsername());
            return billDetail;
        }).collect(Collectors.toList());
        allotBillDetailService.saveOrUpdateBatch(collect);
    }

    private void saveRecord(WarehouseAllotBill allotBill, AllotBillStatusEnum allotBillStatusEnum) {
        String inputStatus = "";
        String outputStatus = "";
        String allotStatus = "";
        String value = allotBillStatusEnum.getValue();
        if (value.equals(AllotBillStatusEnum.审核成功.getValue())) {
            inputStatus = InputBillStatusEnum.已入库.getValue();
            outputStatus = OutputBillStatusEnum.已出库.getValue();
            allotStatus = AllotBillStatusEnum.审核成功.getValue();
        } else {
            inputStatus = InputBillStatusEnum.拒收.getValue();
            outputStatus = OutputBillStatusEnum.拒绝.getValue();
            allotStatus = "待审核";
        }
        List<WarehouseAllotBillDetail> allotBillDetailDtos = allotBill.getAllotBillDetailDtos();
        //出库记录
        WarehouseInputRecordBill inputRecordBill = modelMapper.map(allotBill, WarehouseInputRecordBill.class);
        inputRecordBill.setId(null);
        inputRecordBill.setRecordBillNo(CodeGenUtil.genInputRecordBillNo());
        if (ObjectUtils.isEmpty(inputRecordBill.getCreateTime())) {
            inputRecordBill.setCreateTime(new Date());
        }
        if (ObjectUtils.isEmpty(inputRecordBill.getCreateUserName())) {
            inputRecordBill.setCreateUserName(BaseContextHandler.getUsername());
        }
        if (ObjectUtils.isEmpty(inputRecordBill.getCreateUserId())) {
            inputRecordBill.setCreateUserId(BaseContextHandler.getUserID());
        }
        inputRecordBill.setStatus(inputStatus);
        inputRecordBill.setUpdateTime(new Date());
        inputRecordBill.setUpdateUserId(BaseContextHandler.getUserID());
        inputRecordBill.setUpdateUserName(BaseContextHandler.getUsername());
        inputRecordBill.setType(InputBillTypeEnum.调拨入库.getValue());
        inputRecordBill.setInputBillNo(allotBill.getBillNo());
        inputRecordBill.setInputBillId(allotBill.getId());
        inputRecordBillService.saveOrUpdate(inputRecordBill);

        //入库记录
        WarehouseOutputRecordBill outputRecordBill = modelMapper.map(allotBill, WarehouseOutputRecordBill.class);
        outputRecordBill.setId(null);
        outputRecordBill.setRecordBillNo(CodeGenUtil.genOutputRecordBillNo());
        if (ObjectUtils.isEmpty(outputRecordBill.getCreateTime())) {
            outputRecordBill.setCreateTime(new Date());
        }
        if (ObjectUtils.isEmpty(outputRecordBill.getCreateUserName())) {
            outputRecordBill.setCreateUserName(BaseContextHandler.getUsername());
        }
        if (ObjectUtils.isEmpty(outputRecordBill.getCreateUserId())) {
            outputRecordBill.setCreateUserId(BaseContextHandler.getUserID());
        }
        outputRecordBill.setStatus(outputStatus);
        outputRecordBill.setUpdateTime(new Date());
        outputRecordBill.setUpdateUserId(BaseContextHandler.getUserID());
        outputRecordBill.setUpdateUserName(BaseContextHandler.getUsername());
        outputRecordBill.setType(OutputBillTypeEnum.调拨出库.getValue());
        outputRecordBill.setDestination("调拨");
        outputRecordBill.setOutputBillNo(allotBill.getBillNo());
        outputRecordBill.setOutputBillId(allotBill.getId());
        outputRecordBillService.saveOrUpdate(outputRecordBill);
        //保存调拨单记录
        WarehouseAllotRecordBill recordBill = new WarehouseAllotRecordBill();
        BeanUtils.copyProperties(allotBill, recordBill, "id");
        recordBill.setAllotBillNo(allotBill.getBillNo());
        recordBill.setAllotBillId(allotBill.getId());
        recordBill.setRecordBillNo(allotBill.getBillNo());
        recordBill.setStatus(allotStatus);
        recordBill.setAllotBillId(allotBill.getAllotWarehouseId());
        recordBill.setCreateTime(new Date());
        warehouseAllotRecordBillService.save(recordBill);
        //生成明细记录
        List<WarehouseInputRecordBillDetail> inputRecordBillDetails = new ArrayList<>();
        List<WarehouseOutputRecordBillDetail> outputRecordBillDetails = new ArrayList<>();
        for (WarehouseAllotBillDetail detail : allotBillDetailDtos) {
            WarehouseInputRecordBillDetail inputRecordBillDetail = new WarehouseInputRecordBillDetail();
            BeanUtils.copyProperties(detail, inputRecordBillDetail);
            inputRecordBillDetail.setId(null);
            inputRecordBillDetail.setRecordBillId(inputRecordBill.getId());
            inputRecordBillDetail.setRecordBillNo(inputRecordBill.getRecordBillNo());
            inputRecordBillDetail.setCount(detail.getCount());
            inputRecordBillDetail.setWarehouseId(detail.getAllotWarehouseId());
            inputRecordBillDetail.setWarehouseName(detail.getAllotWarehouseName());
            inputRecordBillDetail.setWarehouseCode(detail.getAllotWarehouseCode());
            if (ObjectUtils.isEmpty(detail.getCreateTime())) {
                inputRecordBillDetail.setCreateTime(new Date());
            }
            if (ObjectUtils.isEmpty(detail.getCreateUserName())) {
                inputRecordBillDetail.setCreateUserName(BaseContextHandler.getUsername());
            }
            if (ObjectUtils.isEmpty(detail.getCreateUserId())) {
                inputRecordBillDetail.setCreateUserId(BaseContextHandler.getUserID());
            }
            inputRecordBillDetail.setUpdateUserId(inputRecordBill.getUpdateUserId());
            inputRecordBillDetail.setUpdateUserName(inputRecordBill.getUpdateUserName());
            inputRecordBillDetail.setUpdateTime(new Date());
            inputRecordBillDetail.setType(InputBillTypeEnum.调拨入库.getValue());
            inputRecordBillDetail.setInputBillNo(allotBill.getBillNo());
            inputRecordBillDetail.setInputBillId(allotBill.getId());
            inputRecordBillDetail.setStatus(inputStatus);
            inputRecordBillDetails.add(inputRecordBillDetail);

            WarehouseOutputRecordBillDetail outputRecordBillDetail = modelMapper.map(detail, WarehouseOutputRecordBillDetail.class);
            outputRecordBillDetail.setId(null);
            outputRecordBillDetail.setRecordBillId(outputRecordBill.getId());
            outputRecordBillDetail.setRecordBillNo(outputRecordBill.getRecordBillNo());
            outputRecordBillDetail.setOutputCount(detail.getCount());
            outputRecordBillDetail.setWarehouseId(detail.getWarehouseId());
            outputRecordBillDetail.setWarehouseName(detail.getWarehouseName());
            outputRecordBillDetail.setWarehouseCode(detail.getWarehouseCode());
            if (ObjectUtils.isEmpty(detail.getCreateTime())) {
                outputRecordBillDetail.setCreateTime(new Date());
            }
            if (ObjectUtils.isEmpty(detail.getCreateUserName())) {
                outputRecordBillDetail.setCreateUserName(BaseContextHandler.getUsername());
            }
            if (ObjectUtils.isEmpty(detail.getCreateUserId())) {
                outputRecordBillDetail.setCreateUserId(BaseContextHandler.getUserID());
            }
            outputRecordBillDetail.setUpdateUserId(outputRecordBill.getUpdateUserId());
            outputRecordBillDetail.setUpdateUserName(outputRecordBill.getUpdateUserName());
            outputRecordBillDetail.setUpdateTime(new Date());
            outputRecordBillDetail.setType(OutputBillTypeEnum.调拨出库.getValue());
            outputRecordBillDetail.setDestination(outputRecordBill.getDestination());
            outputRecordBillDetail.setStatus(outputStatus);
            outputRecordBillDetail.setRequireCount(detail.getCount());
            outputRecordBillDetail.setOutputBillNo(allotBill.getBillNo());
            outputRecordBillDetail.setOutputBillId(allotBill.getId());
            outputRecordBillDetails.add(outputRecordBillDetail);
        }
        //保存调拨单明细记录
        List<WarehouseAllotRecordBillDetail> allotRecordBillDetails = new ArrayList<>();
        String finalAllotStatus = allotStatus;
        allotBillDetailDtos.stream().forEach(detail -> {
            WarehouseAllotRecordBillDetail warehouseAllotRecordBillDetail = new WarehouseAllotRecordBillDetail();
            BeanUtils.copyProperties(detail, warehouseAllotRecordBillDetail, "id");
            warehouseAllotRecordBillDetail.setRecordBillId(recordBill.getId());
            warehouseAllotRecordBillDetail.setRecordBillNo(recordBill.getRecordBillNo());
            warehouseAllotRecordBillDetail.setAllotBillNo(recordBill.getAllotBillNo());
            warehouseAllotRecordBillDetail.setAllotBillId(recordBill.getAllotBillId());
            warehouseAllotRecordBillDetail.setCreateUserId(allotBill.getCreateUserId());
            warehouseAllotRecordBillDetail.setCreateUserName(allotBill.getCreateUserName());
            if (ObjectUtils.isEmpty(allotBill.getUpdateUserId())) {
                warehouseAllotRecordBillDetail.setUpdateUserId(allotBill.getCreateUserId());
            } else {
                warehouseAllotRecordBillDetail.setUpdateUserId(allotBill.getUpdateUserId());
            }
            if (ObjectUtils.isEmpty(allotBill.getUpdateUserName())) {
                warehouseAllotRecordBillDetail.setUpdateUserName(allotBill.getCreateUserName());
            } else {
                warehouseAllotRecordBillDetail.setUpdateUserName(allotBill.getUpdateUserName());
            }
            warehouseAllotRecordBillDetail.setStatus(finalAllotStatus);
            warehouseAllotRecordBillDetail.setCreateTime(new Date());
            warehouseAllotRecordBillDetail.setAllotWarehouseId(Integer.valueOf(String.valueOf(allotBill.getAllotWarehouseId())));
            warehouseAllotRecordBillDetail.setAllotWarehouseName(allotBill.getAllotWarehouseName());
            warehouseAllotRecordBillDetail.setMaterialModelId(Integer.valueOf(String.valueOf(detail.getMaterialModelId())));
            allotRecordBillDetails.add(warehouseAllotRecordBillDetail);
        });
        warehouseAllotRecordBillDetailService.saveBatch(allotRecordBillDetails);
        inputRecordBillDetailService.saveOrUpdateBatch(inputRecordBillDetails);
        outputRecordBillDetailService.saveOrUpdateBatch(outputRecordBillDetails);
    }
}