package com.ktg.iscs.service.impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ktg.common.utils.SecurityUtils;
import com.ktg.common.utils.StringUtils;
import com.ktg.common.utils.bean.BeanUtils;
import com.ktg.iscs.domain.*;
import com.ktg.iscs.domain.dto.hardwareMaterialApi.*;
import com.ktg.iscs.domain.dto.materialsLoan.AddLoanDTO;
import com.ktg.iscs.domain.dto.materialsLoan.ReturnLoanDTO;
import com.ktg.iscs.domain.vo.hardwareMaterialApi.*;
import com.ktg.iscs.domain.vo.materials.MaterialsPageVO;
import com.ktg.iscs.domain.vo.materials.PropertyVO;
import com.ktg.iscs.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 硬件Service业务层处理
 *
 * @author cgj
 * @date 2024-10-16
 */
@Slf4j
@Service
public class HardwareMaterialApiServiceImpl implements HardwareMaterialApiService {
    @Autowired
    private IIsMaterialsService iIsMaterialsService;
    @Autowired
    private IIsMaterialsCabinetService iIsMaterialsCabinetService;
    @Autowired
    private IIsMaterialsTypeService iIsMaterialsTypeService;
    @Autowired
    private IIsMaterialsChangeRecordService isMaterialsChangeRecordService;
    @Autowired
    private IIsMaterialsLoanExceptionService isMaterialsLoanExceptionService;
    @Autowired
    private IIsCabinetOpenRecordService iIsCabinetOpenRecordService;
    @Autowired
    private IIsMaterialsCheckRecordService isMaterialsCheckRecordService;
    @Autowired
    private IIsMaterialsInstructionsService isMaterialsInstructionsService;
    @Autowired
    private IIsMaterialsCheckPlanService iIsMaterialsCheckPlanService;
    @Autowired
    private IIsMaterialsPlanCabinetService iIsMaterialsPlanCabinetService;
    @Autowired
    private IIsMaterialsLoanService iIsMaterialsLoanService;


    @Override
    public List<ExMaterialTypeVO> selectExMaterialTypeById(Long cabinetId, String cabinetCode) throws JsonProcessingException {
        // Assert.notNull(cabinetId, "物资柜ID不能为空！");
        if (cabinetId != null) {
        } else {
            Assert.notBlank(cabinetCode, "物资柜code不能为空！");
            IsMaterialsCabinet cabinet = iIsMaterialsCabinetService.getOne(Wrappers.<IsMaterialsCabinet>lambdaQuery()
                    .eq(IsMaterialsCabinet::getCabinetCode, cabinetCode));
            Assert.isFalse(cabinet == null, "物资柜信息不存在！");
            cabinetId = cabinet.getCabinetId();
        }
        // 0.构造返回值
        ArrayList<ExMaterialTypeVO> exMaterialTypeVOS = new ArrayList<>();
        // 1.查询物资柜下有哪些物资
        List<IsMaterials> materials = iIsMaterialsService.list(Wrappers.<IsMaterials>lambdaQuery()
                .eq(IsMaterials::getMaterialsCabinetId, cabinetId));
        // 1.1如果柜子下有物资，才有继续的必要
        if (!materials.isEmpty()) {
            // 2.找出这些物资有哪些分类，去掉重复的
            Set<Long> materialsTypeIdSet = materials.stream().map(IsMaterials::getMaterialsTypeId).filter(materialsTypeId -> materialsTypeId != null).collect(Collectors.toSet());
            // 2.1查询分类的数据，需要拼接name
            List<IsMaterialsType> isMaterialsTypes = iIsMaterialsTypeService.listByIds(materialsTypeIdSet);
            // 2.2如果这个类型有数据才有意义
            if (!isMaterialsTypes.isEmpty()) {
                // 3.构造’全部‘数据
                ExMaterialTypeVO sumExMaterialTypeVO = new ExMaterialTypeVO();
                sumExMaterialTypeVO.setMaterialsTypeId(0L);
                sumExMaterialTypeVO.setMaterialsTypeName("全部");
                // 承接’全部‘
                int sumExNumber = 0;
                ArrayList<MaterialsPageVO> isMaterials = new ArrayList<>();
                // 解析物资规格
                ObjectMapper objectMapper = new ObjectMapper();
                // 3.1循环构造返回类
                for (IsMaterialsType isMaterialsType : isMaterialsTypes) {
                    ExMaterialTypeVO exMaterialTypeVO = new ExMaterialTypeVO();
                    exMaterialTypeVO.setMaterialsTypeId(isMaterialsType.getMaterialsTypeId());
                    exMaterialTypeVO.setMaterialsTypeName(isMaterialsType.getMaterialsTypeName());
                    exMaterialTypeVO.setMaterialsTypeIcon(isMaterialsType.getMaterialsTypeIcon());
                    exMaterialTypeVO.setMaterialsTypePicture(isMaterialsType.getMaterialsTypePicture());
                    // 过滤获取该类型下的异常物资，1表示损坏 2表示过期
                    List<IsMaterials> exMaterials = materials.stream().filter(o -> o.getMaterialsTypeId().equals(isMaterialsType.getMaterialsTypeId())
                            && ("1".equals(o.getStatus()) || "2".equals(o.getStatus()))).collect(Collectors.toList());
                    // 解析物资规格
                    List<MaterialsPageVO> beans = BeanUtils.toBean(exMaterials, MaterialsPageVO.class);
                    for (MaterialsPageVO record : beans) {
                        // String propertiesValue = propertyVOS.stream().map(PropertyVO::getValueName).collect(Collectors.joining(","));
                        // 目前最多一条
                        if (StringUtils.isNotBlank(record.getProperties())) {
                            List<PropertyVO> propertyVOS = objectMapper.readValue(record.getProperties(), new TypeReference<List<PropertyVO>>() {
                            });
                            record.setPropertiesValueId(propertyVOS.get(0).getRecordId());
                            record.setPropertiesValue(propertyVOS.get(0).getValueName());
                            record.setPropertiesPropertyId(propertyVOS.get(0).getPropertyId());
                            record.setPropertiesProperty(propertyVOS.get(0).getPropertyName());
                        }
                        record.setMaterialsTypeIcon(isMaterialsType.getMaterialsTypeIcon());
                        record.setMaterialsTypePicture(isMaterialsType.getMaterialsTypePicture());
                    }
                    exMaterialTypeVO.setExNumber(exMaterials.size());
                    exMaterialTypeVO.setMaterials(beans);
                    exMaterialTypeVOS.add(exMaterialTypeVO);
                    // ’全部‘累加
                    sumExNumber = sumExNumber + exMaterials.size();
                    // ’全部‘集合
                    isMaterials.addAll(beans);
                }
                // 3.2将‘全部’的数据补充完整
                sumExMaterialTypeVO.setExNumber(sumExNumber);
                sumExMaterialTypeVO.setMaterials(isMaterials);
                exMaterialTypeVOS.add(0, sumExMaterialTypeVO);
            }
        }
        return exMaterialTypeVOS;
    }

    @Override
    public Boolean checkReplaceData(ReplaceMaterialDTO dto) {
        Assert.notNull(dto.getOldMaterialsId(), "旧物资ID不能为空!");
        Assert.notBlank(dto.getMaterialsRfid(), "新物资RFID不能为空!");
        // 1.获取旧物资信息
        IsMaterials oldMaterials = iIsMaterialsService.getById(dto.getOldMaterialsId());
        // 判断旧物资和新物资的rfid是否更换
        if (dto.getMaterialsRfid().equals(oldMaterials.getMaterialsRfid())) {
            // 2.没有更换rfid


        } else {
            // 3.更换rfid
            // 判断是否在柜子外 判断rfid是否重复，如果重复，判断重复数据是否绑定物资柜，如果没有绑定直接用，如果绑定，报异常
            Assert.isFalse(oldMaterials.getLoanState().equals("1"), "需要更换的物资未取出！");
            // 判断新物资RFID是否被使用
            IsMaterials one = iIsMaterialsService.getOne(Wrappers.<IsMaterials>lambdaQuery()
                    .eq(IsMaterials::getMaterialsRfid, dto.getMaterialsRfid()));
            Assert.isFalse(one != null && one.getMaterialsCabinetId() != null && one.getMaterialsCabinetId() != 0, "该RFID已被使用！");
            // 判断新物资是否在物资当前柜子中
            /*if (one != null) {
                IsMaterialsLoanException one1 = isMaterialsLoanExceptionService.getOne(Wrappers.<IsMaterialsLoanException>lambdaQuery()
                        .eq(IsMaterialsLoanException::getMaterialsRfid, dto.getMaterialsRfid())
                        .eq(IsMaterialsLoanException::getStatus, 0)
                        .eq(IsMaterialsLoanException::getRestitutionToId, oldMaterials.getMaterialsCabinetId())
                        .orderByDesc(IsMaterialsLoanException::getMisplaceId)
                        .last("offset 0 rows fetch next 1 rows only"));
                Assert.isTrue(one1 != null, "请在该柜中放入新物资！");
            }*/

        }
        return true;
    }

    @Transactional
    @Override
    public Boolean insertCheckedRecord(ReplaceMaterialParamDTO dto) throws JsonProcessingException {
        Assert.isFalse(dto.getList().isEmpty(), "没有确定要维修或更换的物资！");
        Long cabinetId = null;
        // 因为比较复杂，循环处理
        for (ReplaceMaterialDTO replaceMaterialDTO : dto.getList()) {
            Boolean b = checkReplaceData(replaceMaterialDTO);
            if (!b) {
                System.out.println("进来了-------------------");
                continue;
            }
            Assert.notNull(replaceMaterialDTO.getOldMaterialsId(), "旧物资ID不能为空！");
            IsMaterials oldMaterial = iIsMaterialsService.getById(replaceMaterialDTO.getOldMaterialsId());
            cabinetId = oldMaterial.getMaterialsCabinetId();
            // 查询该物资的最新报异常记录
            IsMaterialsCheckRecord checkRecord = isMaterialsCheckRecordService.getOne(Wrappers.<IsMaterialsCheckRecord>lambdaQuery()
                    .eq(IsMaterialsCheckRecord::getMaterialsId, replaceMaterialDTO.getOldMaterialsId())
                    .eq(IsMaterialsCheckRecord::getStatus, "1")
                    .orderByDesc(IsMaterialsCheckRecord::getRecordId)
                    .last("offset 0 rows fetch next 1 rows only"));
            // 判断物资是不是维修，如果是维修，做维修处理
            if (StringUtils.isNotBlank(replaceMaterialDTO.getMeasure()) && replaceMaterialDTO.getMeasure().equals("维修")) {
                // 如果是维修直接更新物资状态
                iIsMaterialsService.update(Wrappers.<IsMaterials>lambdaUpdate()
                        .eq(IsMaterials::getMaterialsId, replaceMaterialDTO.getOldMaterialsId())
                        .set(IsMaterials::getStatus, "0"));
                // 生成维修记录
                IsMaterialsChangeRecord isMaterialsChangeRecord = new IsMaterialsChangeRecord();
                isMaterialsChangeRecord.setOldMaterialsId(replaceMaterialDTO.getOldMaterialsId());
                isMaterialsChangeRecord.setOldMaterialsRfid(oldMaterial.getMaterialsRfid());
                isMaterialsChangeRecord.setNewMaterialsId(oldMaterial.getMaterialsId());
                isMaterialsChangeRecord.setNewMaterialsRfid(oldMaterial.getMaterialsRfid());
                isMaterialsChangeRecord.setChangeUserId(SecurityUtils.getUserId());
                isMaterialsChangeRecord.setChangeDate(new Date());
                isMaterialsChangeRecord.setChangeType("0");
                isMaterialsChangeRecord.setOperateType("3");
                isMaterialsChangeRecord.setCheckRecordId(checkRecord != null ? checkRecord.getRecordId() : null);
                isMaterialsChangeRecordService.save(isMaterialsChangeRecord);
                return true;
            }

            // 1.对旧物资进行处理，如果新物资需要使用旧物资的rfid，则把旧物资的rfid清理掉，然后绑定给新物资，最后开柜门拿出旧物资解绑就可以了
            if (StringUtils.isNotBlank(oldMaterial.getMaterialsRfid()) && oldMaterial.getMaterialsRfid().equals(replaceMaterialDTO.getMaterialsRfid())) {
                // 1.1该情况属于新物资需要使用旧物资的rfid
                iIsMaterialsService.update(Wrappers.<IsMaterials>lambdaUpdate()
                        .eq(IsMaterials::getMaterialsId, replaceMaterialDTO.getOldMaterialsId())
                        .set(IsMaterials::getMaterialsCabinetId, null)
                        .set(IsMaterials::getMaterialsRfid, null));
            }
            // 1.2无论是否更换rfid，新物资的数据都要存储到物资清单之中
            IsMaterials newMaterial = new IsMaterials();
            if (oldMaterial.getMaterialsRfid().equals(replaceMaterialDTO.getMaterialsRfid())) {
                // 如果更换物资的rfid相同
                newMaterial.setMaterialsName(replaceMaterialDTO.getMaterialsName());
                newMaterial.setMaterialsTypeId(replaceMaterialDTO.getMaterialsTypeId());
                newMaterial.setMaterialsCabinetId(oldMaterial.getMaterialsCabinetId());
                newMaterial.setLoanState(oldMaterial.getLoanState());
                newMaterial.setMaterialsRfid(replaceMaterialDTO.getMaterialsRfid());
                newMaterial.setSupplier(oldMaterial.getSupplier());
                newMaterial.setExpirationDate(replaceMaterialDTO.getExpirationDate());
                newMaterial.setStatus("0");

                PropertyVO propertyVO = new PropertyVO();
                propertyVO.setPropertyId(String.valueOf(replaceMaterialDTO.getPropertiesPropertyId()));
                propertyVO.setPropertyName(replaceMaterialDTO.getPropertiesProperty());
                propertyVO.setRecordId(String.valueOf(replaceMaterialDTO.getPropertiesValueId()));
                propertyVO.setValueName(replaceMaterialDTO.getPropertiesValue());
                // 使用 ObjectMapper 将对象转换为 JSON 字符串
                ObjectMapper objectMapper = new ObjectMapper();
                String jsonString = objectMapper.writeValueAsString(propertyVO);
                newMaterial.setProperties("[" + jsonString + "]");
                iIsMaterialsService.save(newMaterial);
            }

            IsMaterials newMaterials = iIsMaterialsService.getOne(Wrappers.<IsMaterials>lambdaQuery()
                    .eq(IsMaterials::getMaterialsRfid, replaceMaterialDTO.getMaterialsRfid()));
            if (!oldMaterial.getMaterialsRfid().equals(replaceMaterialDTO.getMaterialsRfid()) && newMaterials == null) {
                // 如果更换rfid，并且不在系统内的数据
                newMaterial.setMaterialsName(replaceMaterialDTO.getMaterialsName());
                newMaterial.setMaterialsTypeId(replaceMaterialDTO.getMaterialsTypeId());
                newMaterial.setMaterialsCabinetId(oldMaterial.getMaterialsCabinetId());
                newMaterial.setLoanState("1");
                newMaterial.setMaterialsRfid(replaceMaterialDTO.getMaterialsRfid());
                newMaterial.setSupplier(oldMaterial.getSupplier());
                newMaterial.setExpirationDate(replaceMaterialDTO.getExpirationDate());
                newMaterial.setStatus("0");

                PropertyVO propertyVO = new PropertyVO();
                propertyVO.setPropertyId(String.valueOf(replaceMaterialDTO.getPropertiesPropertyId()));
                propertyVO.setPropertyName(replaceMaterialDTO.getPropertiesProperty());
                propertyVO.setRecordId(String.valueOf(replaceMaterialDTO.getPropertiesValueId()));
                propertyVO.setValueName(replaceMaterialDTO.getPropertiesValue());
                // 使用 ObjectMapper 将对象转换为 JSON 字符串
                ObjectMapper objectMapper = new ObjectMapper();
                String jsonString = objectMapper.writeValueAsString(propertyVO);
                newMaterial.setProperties("[" + jsonString + "]");
                iIsMaterialsService.save(newMaterial);

                // 将旧物资解绑
                iIsMaterialsService.update(Wrappers.<IsMaterials>lambdaUpdate()
                        .eq(IsMaterials::getMaterialsRfid, oldMaterial.getMaterialsRfid())
                        .set(IsMaterials::getMaterialsCabinetId, null));
            }

            if (!oldMaterial.getMaterialsRfid().equals(replaceMaterialDTO.getMaterialsRfid()) && newMaterials != null) {
                // 如果发现物资是存在的，判断下有没有绑定柜子
                Assert.isFalse(newMaterials.getMaterialsCabinetId() != null && newMaterials.getMaterialsCabinetId() != 0, "该物资存在所属柜子，不可更换！");
                Assert.isTrue(newMaterials.getStatus().equals("0"), "更换的物资异常，不可更换！");
                // 如果没有绑定柜子，则可以开始绑定
                iIsMaterialsService.update(Wrappers.<IsMaterials>lambdaUpdate()
                        .eq(IsMaterials::getMaterialsId, newMaterials.getMaterialsId())
                        .set(IsMaterials::getMaterialsCabinetId, oldMaterial.getMaterialsCabinetId()));
                // 解绑老物资
                iIsMaterialsService.update(Wrappers.<IsMaterials>lambdaUpdate()
                        .eq(IsMaterials::getMaterialsId, oldMaterial.getMaterialsId())
                        .set(IsMaterials::getMaterialsCabinetId, null));
            }

            // 2.新增物资更换记录
            IsMaterialsChangeRecord isMaterialsChangeRecord = new IsMaterialsChangeRecord();
            isMaterialsChangeRecord.setOldMaterialsId(replaceMaterialDTO.getOldMaterialsId());
            isMaterialsChangeRecord.setOldMaterialsRfid(oldMaterial.getMaterialsRfid());
            isMaterialsChangeRecord.setNewMaterialsId(newMaterial.getMaterialsId());
            isMaterialsChangeRecord.setNewMaterialsRfid(newMaterial.getMaterialsRfid());
            isMaterialsChangeRecord.setChangeUserId(SecurityUtils.getUserId());
            isMaterialsChangeRecord.setChangeDate(new Date());
            isMaterialsChangeRecord.setChangeType("0");

            if (checkRecord != null) {
                isMaterialsChangeRecord.setCheckRecordId(checkRecord.getRecordId());
            } else {
                isMaterialsChangeRecord.setCheckRecordId(0L);
            }
            isMaterialsChangeRecordService.save(isMaterialsChangeRecord);

            // 删除旧物资的取出记录和新物资的存入异常---曹特殊要求，改成完成的数据
            iIsMaterialsLoanService.update(Wrappers.<IsMaterialsLoan>lambdaUpdate()
                    .eq(IsMaterialsLoan::getMaterialsId, oldMaterial.getMaterialsId())
                    .ne(IsMaterialsLoan::getStatus, "1")
                    .set(IsMaterialsLoan::getRemark, "物资更换")
                    .set(IsMaterialsLoan::getStatus, "1")
                    .set(IsMaterialsLoan::getRestitutionUserId, SecurityUtils.getUserId())
                    .set(IsMaterialsLoan::getActualRestitutionTime, new Date()));
            // 删除新物资的存入异常---曹特殊要求，改成完成的数据
            isMaterialsLoanExceptionService.update(Wrappers.<IsMaterialsLoanException>lambdaUpdate()
                    .eq(IsMaterialsLoanException::getMaterialsRfid, replaceMaterialDTO.getMaterialsRfid())
                    .eq(IsMaterialsLoanException::getStatus, "0")
                    .set(IsMaterialsLoanException::getRemark, "物资更换")
                    .set(IsMaterialsLoanException::getStatus, "1")
                    .set(IsMaterialsLoanException::getHandleTime, new Date()));
        }
        // 更新检查记录
        if (cabinetId != null) {
            IsMaterialsCabinet byId = iIsMaterialsCabinetService.getById(cabinetId);
            if (byId != null) {
                iIsMaterialsPlanCabinetService.autoChangeCheckRecord(byId.getCabinetCode());
            }
        }
        return true;
    }

    @Transactional
    @Override
    public Boolean insertReplaceRecord(ReplaceMaterialParamDTO dto) throws JsonProcessingException {
        Assert.isFalse(dto.getList().isEmpty(), "没有确定要维修或更换的物资！");
        // 因为比较复杂，循环处理
        for (ReplaceMaterialDTO replaceMaterialDTO : dto.getList()) {
            Assert.notNull(replaceMaterialDTO.getOldMaterialsId(), "旧物资ID不能为空！");
            IsMaterials oldMaterial = iIsMaterialsService.getById(replaceMaterialDTO.getOldMaterialsId());
            // 1.查询该物资的最新报异常记录
            IsMaterialsCheckRecord checkRecord = isMaterialsCheckRecordService.getOne(Wrappers.<IsMaterialsCheckRecord>lambdaQuery()
                    .eq(IsMaterialsCheckRecord::getMaterialsId, replaceMaterialDTO.getOldMaterialsId())
                    .eq(IsMaterialsCheckRecord::getStatus, "1")
                    .orderByDesc(IsMaterialsCheckRecord::getRecordId)
                    .last("offset 0 rows fetch next 1 rows only"));
            if (checkRecord != null && StringUtils.isNotBlank(checkRecord.getMeasure()) && checkRecord.getMeasure().equals("维修")) {
                // 如果是维修直接更新物资状态
                iIsMaterialsService.update(Wrappers.<IsMaterials>lambdaUpdate()
                        .eq(IsMaterials::getMaterialsId, replaceMaterialDTO.getOldMaterialsId())
                        .set(IsMaterials::getStatus, "0"));
                // 生成维修记录
                IsMaterialsChangeRecord isMaterialsChangeRecord = new IsMaterialsChangeRecord();
                isMaterialsChangeRecord.setOldMaterialsId(replaceMaterialDTO.getOldMaterialsId());
                isMaterialsChangeRecord.setOldMaterialsRfid(oldMaterial.getMaterialsRfid());
                isMaterialsChangeRecord.setNewMaterialsId(oldMaterial.getMaterialsId());
                isMaterialsChangeRecord.setNewMaterialsRfid(oldMaterial.getMaterialsRfid());
                isMaterialsChangeRecord.setChangeUserId(SecurityUtils.getUserId());
                isMaterialsChangeRecord.setChangeDate(new Date());
                isMaterialsChangeRecord.setChangeType("0");
                isMaterialsChangeRecord.setOperateType("3");
                isMaterialsChangeRecord.setCheckRecordId(checkRecord.getRecordId());
                isMaterialsChangeRecordService.save(isMaterialsChangeRecord);
                return true;
            }
            // 2.对旧物资进行处理，如果新物资需要使用旧物资的rfid，则把旧物资的rfid清理掉，然后绑定给新物资，最后开柜门拿出旧物资解绑就可以了
            if (StringUtils.isNotBlank(oldMaterial.getMaterialsRfid()) && oldMaterial.getMaterialsRfid().equals(replaceMaterialDTO.getMaterialsRfid())) {
                // 2.1该情况属于新物资需要使用旧物资的rfid
                iIsMaterialsService.update(Wrappers.<IsMaterials>lambdaUpdate()
                        .eq(IsMaterials::getMaterialsId, replaceMaterialDTO.getOldMaterialsId())
                        .set(IsMaterials::getMaterialsCabinetId, null)
                        .set(IsMaterials::getMaterialsRfid, null));
            }
            // 2.2无论是否更换rfid，新物资的数据都要存储到物资清单之中
            IsMaterials newMaterial = new IsMaterials();
            newMaterial.setMaterialsName(replaceMaterialDTO.getMaterialsName());
            newMaterial.setMaterialsTypeId(replaceMaterialDTO.getMaterialsTypeId());
            newMaterial.setMaterialsCabinetId(oldMaterial.getMaterialsCabinetId());
            newMaterial.setLoanState("0");
            newMaterial.setMaterialsRfid(replaceMaterialDTO.getMaterialsRfid());
            newMaterial.setSupplier(oldMaterial.getSupplier());
            newMaterial.setExpirationDate(replaceMaterialDTO.getExpirationDate());
            newMaterial.setStatus("0");

            PropertyVO propertyVO = new PropertyVO();
            propertyVO.setPropertyId(String.valueOf(replaceMaterialDTO.getPropertiesPropertyId()));
            propertyVO.setPropertyName(replaceMaterialDTO.getPropertiesProperty());
            propertyVO.setRecordId(String.valueOf(replaceMaterialDTO.getPropertiesValueId()));
            propertyVO.setValueName(replaceMaterialDTO.getPropertiesValue());
            // 使用 ObjectMapper 将对象转换为 JSON 字符串
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonString = objectMapper.writeValueAsString(propertyVO);
            newMaterial.setProperties("[" + jsonString + "]");
            iIsMaterialsService.save(newMaterial);

            // 3.新增物资更换记录
            IsMaterialsChangeRecord isMaterialsChangeRecord = new IsMaterialsChangeRecord();
            isMaterialsChangeRecord.setOldMaterialsId(replaceMaterialDTO.getOldMaterialsId());
            isMaterialsChangeRecord.setOldMaterialsRfid(oldMaterial.getMaterialsRfid());
            isMaterialsChangeRecord.setNewMaterialsId(newMaterial.getMaterialsId());
            isMaterialsChangeRecord.setNewMaterialsRfid(newMaterial.getMaterialsRfid());
            isMaterialsChangeRecord.setChangeUserId(SecurityUtils.getUserId());
            isMaterialsChangeRecord.setChangeDate(new Date());
            isMaterialsChangeRecord.setChangeType("0");
            if (checkRecord != null) {
                isMaterialsChangeRecord.setCheckRecordId(checkRecord.getRecordId());
            } else {
                isMaterialsChangeRecord.setCheckRecordId(0L);
            }
            isMaterialsChangeRecordService.save(isMaterialsChangeRecord);
        }
        return true;
    }

    @Override
    public Boolean updateMaterialsReplace(ReplaceMaterialsDTO dto) {
        Assert.notBlank(dto.getCabinetCode(), "物资柜不能为空!");
        IsMaterialsCabinet cabinetByCode = iIsMaterialsCabinetService.getCabinetByCode(dto.getCabinetCode());
        // 1.开始解绑
        if (!dto.getUnbindMaterialRfidList().isEmpty()) {
            iIsMaterialsService.update(Wrappers.<IsMaterials>lambdaUpdate()
                    .in(IsMaterials::getMaterialsRfid, dto.getUnbindMaterialRfidList())
                    .set(IsMaterials::getMaterialsCabinetId, null)
                    .set(IsMaterials::getLoanState, "0"));
        }
        // 2.开始绑定
        if (!dto.getBindingMaterialRfidList().isEmpty()) {
            iIsMaterialsService.update(Wrappers.<IsMaterials>lambdaUpdate()
                    .in(IsMaterials::getMaterialsRfid, dto.getBindingMaterialRfidList())
                    .set(IsMaterials::getMaterialsCabinetId, cabinetByCode.getCabinetId())
                    .set(IsMaterials::getLoanState, "1")
                    .set(IsMaterials::getStatus, "0"));
        }
        return true;
    }

    @Override
    public Boolean insertCabinetOpenTimeout(OpenTimeoutDTO dto) {
        // Assert.notNull(dto.getLoanFromId(), "物资柜不能为空");
        if (dto.getLoanFromId() != null) {
        } else {
            Assert.notBlank(dto.getLoanFromCode(), "物资柜code不能空！");
            IsMaterialsCabinet cabinetByCode = iIsMaterialsCabinetService.getCabinetByCode(dto.getLoanFromCode());
            Assert.isTrue(cabinetByCode != null, "物资柜不存在！");
            dto.setLoanFromId(cabinetByCode.getCabinetId());
        }
        IsMaterialsLoanException loanException = new IsMaterialsLoanException();
        loanException.setLoanFromId(dto.getLoanFromId());
        loanException.setRestitutionUserId(SecurityUtils.getUserId());
        loanException.setOccurTime(new Date());
        loanException.setExceptionType("1");
        isMaterialsLoanExceptionService.save(loanException);
        return true;
    }

    @Override
    public Boolean updateCabinetOpenTimeout(OpenTimeoutDTO dto) {
        // Assert.notNull(dto.getLoanFromId(), "物资柜不能为空");
        if (dto.getLoanFromId() != null) {
        } else {
            Assert.notBlank(dto.getLoanFromCode(), "物资柜code不能空！");
            IsMaterialsCabinet cabinetByCode = iIsMaterialsCabinetService.getCabinetByCode(dto.getLoanFromCode());
            Assert.isTrue(cabinetByCode != null, "物资柜不存在！");
            dto.setLoanFromId(cabinetByCode.getCabinetId());
        }
        isMaterialsLoanExceptionService.update(Wrappers.<IsMaterialsLoanException>lambdaUpdate()
                .eq(IsMaterialsLoanException::getLoanFromId, dto.getLoanFromId())
                .eq(IsMaterialsLoanException::getExceptionType, "1")
                .eq(IsMaterialsLoanException::getStatus, "0")
                .set(IsMaterialsLoanException::getStatus, "1")
                .set(IsMaterialsLoanException::getHandleTime, new Date()));
        return true;
    }

    @Override
    public Boolean insertCabinetOpenRecord(IsCabinetOpenRecord dto) {
        // Assert.notNull(dto.getCabinetId(), "物资柜ID不能为空！");
        if (dto.getCabinetId() != null) {
        } else {
            Assert.notBlank(dto.getCabinetCode(), "请告诉我物资柜code！");
            IsMaterialsCabinet one = iIsMaterialsCabinetService.getOne(Wrappers.<IsMaterialsCabinet>lambdaQuery()
                    .eq(IsMaterialsCabinet::getCabinetCode, dto.getCabinetCode()));
            Assert.isFalse(one == null, "物资柜信息不存在!");
            dto.setCabinetId(one.getCabinetId());
        }
        Assert.notBlank(dto.getOpenType(), "开门类型不可为空！");
        dto.setOpenTime(new Date());
        dto.setUserId(String.valueOf(SecurityUtils.getUserId()));
        iIsCabinetOpenRecordService.save(dto);
        return true;
    }

    @Override
    public Boolean updateCabinetClose(IsCabinetOpenRecord dto) {
        // Assert.notNull(dto.getCabinetId(), "物资柜ID不能为空！");
        if (dto.getCabinetId() != null) {
        } else {
            Assert.notBlank(dto.getCabinetCode(), "请告诉我物资柜code！");
            IsMaterialsCabinet one = iIsMaterialsCabinetService.getOne(Wrappers.<IsMaterialsCabinet>lambdaQuery()
                    .eq(IsMaterialsCabinet::getCabinetCode, dto.getCabinetCode()));
            Assert.isFalse(one == null, "物资柜信息不存在!");
            dto.setCabinetId(one.getCabinetId());
        }
        iIsCabinetOpenRecordService.update(Wrappers.<IsCabinetOpenRecord>lambdaUpdate()
                .eq(IsCabinetOpenRecord::getCabinetId, dto.getCabinetId())
                .isNull(IsCabinetOpenRecord::getCloseTime)
                .set(IsCabinetOpenRecord::getCloseTime, new Date()));
        // 检查该柜子有没有关门异常，如果有现在解除一下
        isMaterialsLoanExceptionService.update(Wrappers.<IsMaterialsLoanException>lambdaUpdate()
                .eq(IsMaterialsLoanException::getLoanFromId, dto.getCabinetId())
                .eq(IsMaterialsLoanException::getExceptionType, "1")
                .eq(IsMaterialsLoanException::getStatus, "0")
                .set(IsMaterialsLoanException::getStatus, "1")
                .set(IsMaterialsLoanException::getHandleTime, new Date()));
        return true;
    }

    @Override
    public List<CabinetMaterialVO> selectMaterialsByCabinetId(Long cabinetId, String cabinetCode) {
        Assert.isFalse(cabinetId == null && StringUtils.isBlank(cabinetCode), "请告诉我物资柜身份(cabinetId / cabinetCode)!");
        if (cabinetId != null) {
        } else {
            IsMaterialsCabinet one = iIsMaterialsCabinetService.getOne(Wrappers.<IsMaterialsCabinet>lambdaQuery()
                    .eq(IsMaterialsCabinet::getCabinetCode, cabinetCode));
            Assert.isFalse(one == null, "无法识别" + cabinetCode + "物资柜身份!");
            cabinetId = one.getCabinetId();
        }
        // 0.构造返回值
        ArrayList<CabinetMaterialVO> vo = new ArrayList<>();
        // 1.查询物资柜下有哪些物资
        List<IsMaterials> materials = iIsMaterialsService.list(Wrappers.<IsMaterials>lambdaQuery()
                .eq(IsMaterials::getMaterialsCabinetId, cabinetId));
        // 1.1如果柜子下有物资，才有继续的必要
        if (!materials.isEmpty()) {
            // 4.给物资赋值最新一次借取人员的数据
            List<IsMaterials> collect = materials.stream().filter(o -> StringUtils.isNotBlank(o.getLoanState()) && o.getLoanState().equals("0")).collect(Collectors.toList());
            if (!collect.isEmpty()) {
                List<Long> collect1 = collect.stream().map(IsMaterials::getMaterialsId).collect(Collectors.toList());
                List<Long> lastLoanRecordIds = iIsMaterialsLoanService.getLastLoanRecord(collect1);
                if (!lastLoanRecordIds.isEmpty()) {
                    List<IsMaterialsLoan> isMaterialsLoans = iIsMaterialsLoanService.listByIds(lastLoanRecordIds);
                    for (IsMaterialsLoan isMaterialsLoan : isMaterialsLoans) {
                        for (IsMaterials material : materials) {
                            if (isMaterialsLoan.getMaterialsId().equals(material.getMaterialsId())) {
                                material.setLoanUserId(isMaterialsLoan.getLoanUserId());
                            }
                        }
                    }
                }
            }

            // 2.找出这些物资有哪些分类，去掉重复的
            Set<Long> materialsTypeIdSet = materials.stream().map(IsMaterials::getMaterialsTypeId).filter(materialsTypeId -> materialsTypeId != null).collect(Collectors.toSet());
            // 2.1查询分类的数据，需要拼接name
            List<IsMaterialsType> isMaterialsTypes = iIsMaterialsTypeService.listByIds(materialsTypeIdSet);
            // 2.2如果这个类型有数据才有意义
            if (!isMaterialsTypes.isEmpty()) {
                // 3.构造’全部‘数据
                CabinetMaterialVO sumExMaterialTypeVO = new CabinetMaterialVO();
                sumExMaterialTypeVO.setMaterialsTypeId(0L);
                sumExMaterialTypeVO.setMaterialsTypeName("全部");
                // 承接’全部‘
                int sumNumber = 0;
                ArrayList<MaterialsPageVO> isMaterials = new ArrayList<>();
                // 3.1循环构造返回类
                for (IsMaterialsType isMaterialsType : isMaterialsTypes) {
                    CabinetMaterialVO cabinetMaterialVO = new CabinetMaterialVO();
                    cabinetMaterialVO.setMaterialsTypeId(isMaterialsType.getMaterialsTypeId());
                    cabinetMaterialVO.setMaterialsTypeName(isMaterialsType.getMaterialsTypeName());
                    // 过滤获取该类型下的异常物资，1表示损坏 2表示过期
                    List<IsMaterials> exMaterials = materials.stream().filter(o -> o.getMaterialsTypeId() != null
                            && isMaterialsType.getMaterialsTypeId() != null
                            && o.getMaterialsTypeId().equals(isMaterialsType.getMaterialsTypeId())).collect(Collectors.toList());
                    // 解析物资规格
                    List<MaterialsPageVO> beans = BeanUtils.toBean(exMaterials, MaterialsPageVO.class);
                    for (MaterialsPageVO record : beans) {
                        record.setMaterialsTypeIcon(isMaterialsType.getMaterialsTypeIcon());
                        record.setMaterialsTypePicture(isMaterialsType.getMaterialsTypePicture());
                        record.setMaterialsTypeName(isMaterialsType.getMaterialsTypeName());
                    }
                    cabinetMaterialVO.setNumber(exMaterials.size());
                    cabinetMaterialVO.setBorrowableNumber((int) exMaterials.stream().filter(o -> o.getStatus().equals("0") && o.getLoanState().equals("1")).count());
                    cabinetMaterialVO.setMaterialsTypeIcon(isMaterialsType.getMaterialsTypeIcon());
                    cabinetMaterialVO.setMaterialsTypePicture(isMaterialsType.getMaterialsTypePicture());
                    cabinetMaterialVO.setMaterials(beans);
                    vo.add(cabinetMaterialVO);
                    // ’全部‘累加
                    sumNumber = sumNumber + exMaterials.size();
                    // ’全部‘集合
                    isMaterials.addAll(beans);
                }
                // 3.2将‘全部’的数据补充完整
                sumExMaterialTypeVO.setNumber(sumNumber);
                sumExMaterialTypeVO.setMaterials(isMaterials);
                vo.add(0, sumExMaterialTypeVO);
            }
        }
        return vo;
    }

    @Override
    public IsMaterials selectMaterialByRfid(String rfid) {
        Assert.notBlank(rfid, "物资RFID不能为空!");
        IsMaterials materials = iIsMaterialsService.getOne(Wrappers.<IsMaterials>lambdaQuery()
                .eq(IsMaterials::getMaterialsRfid, rfid));
        if (materials != null && materials.getMaterialsTypeId() != null) {
            IsMaterialsType materialsType = iIsMaterialsTypeService.getById(materials.getMaterialsTypeId());
            if (materialsType != null) {
                materials.setMaterialsTypeIcon(materialsType.getMaterialsTypeIcon());
                materials.setMaterialsTypePicture(materialsType.getMaterialsTypePicture());
                materials.setPropertyIds(materialsType.getPropertyIds());
            }
        }
        return materials;
    }

    @Override
    public List<IsMaterials> selectMaterialsByRfidList(RfidListDTO dto) {
        Assert.isFalse(dto.getList().isEmpty(), "物资RFID不能为空!");
        List<IsMaterials> materialsList = iIsMaterialsService.list(Wrappers.<IsMaterials>lambdaQuery()
                .in(IsMaterials::getMaterialsRfid, dto.getList()));
        if (!materialsList.isEmpty()) {
            List<Long> materialsTypeIds = materialsList.stream().map(IsMaterials::getMaterialsTypeId).distinct().collect(Collectors.toList());
            if (!materialsTypeIds.isEmpty()) {
                List<IsMaterialsType> isMaterialsTypes = iIsMaterialsTypeService.listByIds(materialsTypeIds);
                for (IsMaterials materials : materialsList) {
                    for (IsMaterialsType materialsType : isMaterialsTypes) {
                        if (materials.getMaterialsTypeId().equals(materialsType.getMaterialsTypeId())) {
                            materials.setMaterialsTypeIcon(materialsType.getMaterialsTypeIcon());
                            materials.setMaterialsTypePicture(materialsType.getMaterialsTypePicture());
                            materials.setPropertyIds(materialsType.getPropertyIds());
                        }
                    }
                }
            }
        }
        return materialsList;
    }

    @Override
    public CabinetMaterialsVO selectCabinetMaterials(CabinetRfidListDTO dto) {
        Assert.notBlank(dto.getCabinetCode(), "物资柜子code不能为空！");
        Assert.isFalse(dto.getList().isEmpty(), "物资中无物资！");
        IsMaterialsCabinet cabinet = iIsMaterialsCabinetService.getCabinetByCode(dto.getCabinetCode());
        Assert.isFalse(cabinet == null, dto.getCabinetCode() + "物资柜code不存在！");
        List<IsMaterials> list = iIsMaterialsService.list(Wrappers.<IsMaterials>lambdaQuery()
                .eq(IsMaterials::getMaterialsCabinetId, cabinet.getCabinetId())
                .in(IsMaterials::getMaterialsRfid, dto.getList()));
        // 假设都是不属于该柜子的
        List<String> notCabinetRfidList = dto.getList();
        // 属于该柜子的rfid
        List<String> cabinetRfidList = new ArrayList<>();
        if (!list.isEmpty()) {
            cabinetRfidList = list.stream().map(IsMaterials::getMaterialsRfid).collect(Collectors.toList());
            // 把假设的里面的是属于该柜子的删除掉
            notCabinetRfidList.removeIf(cabinetRfidList::contains);
        }
        CabinetMaterialsVO cabinetMaterialsVO = new CabinetMaterialsVO();
        cabinetMaterialsVO.setIsMaterialsCabinet(cabinet);
        cabinetMaterialsVO.setCabinetRfidList(cabinetRfidList);
        cabinetMaterialsVO.setNotCabinetRfidList(notCabinetRfidList);
        return cabinetMaterialsVO;
    }

    @Override
    public String updateMaterialReceiveReturn(RecRetParamDTO recRetParamDTO) {
        if (!recRetParamDTO.getList().isEmpty()) {
            Long userId = SecurityUtils.getUserId();
            List<String> failRfidList = new ArrayList<>();
            for (RecRetMaterialDTO dto : recRetParamDTO.getList()) {
                // 1.断言判断
                Assert.notBlank(dto.getMaterialsRfid(), "请告诉我物资的rfid!");
                Assert.notBlank(dto.getLoanState(), "请告诉我是借出还是归还!");
                try {
                    // 1.1 开始查询物资，物资柜传的rfid
                    IsMaterials materials = iIsMaterialsService.getOne(Wrappers.<IsMaterials>lambdaQuery()
                            .eq(IsMaterials::getMaterialsRfid, dto.getMaterialsRfid()));
                    Assert.isFalse(materials == null, "通过RFID:" + dto.getMaterialsRfid() + "未查询到物资！");
                    // 如果物资是借出状态，又来借出就报错
                    if ("0".equals(materials.getLoanState()) && "0".equals(dto.getLoanState())) {
                        failRfidList.add(dto.getMaterialsRfid() + "物资已经是借出状态，无法再借出！");
                        Assert.isFalse(true, dto.getMaterialsRfid() + "物资已经是借出状态，无法再借出！");
                    }
                    // 如果已经再柜中，又来放入
                    if ("1".equals(materials.getLoanState()) && "1".equals(dto.getLoanState())) {
                        failRfidList.add(dto.getMaterialsRfid() + "物资已经是柜中状态，无法再放入！");
                        Assert.isFalse(true, dto.getMaterialsRfid() + "物资已经是柜中状态，无法再放入！");
                    }
                    // 2.开始更新物资状态
                    iIsMaterialsService.update(Wrappers.<IsMaterials>lambdaUpdate()
                            .eq(IsMaterials::getMaterialsRfid, dto.getMaterialsRfid())
                            .set(IsMaterials::getLoanState, dto.getLoanState())
                            .set(IsMaterials::getUpdateTime, new Date()));
                    // 4.开始更新借出表信息
                    if ("0".equals(dto.getLoanState())) {
                        // 4.1开始新增借出记录表
                        AddLoanDTO addMaterialsLoan = new AddLoanDTO();
                        addMaterialsLoan.setMaterialsId(materials.getMaterialsId());
                        addMaterialsLoan.setLoanUserId(userId);
                        iIsMaterialsLoanService.insertIsMaterialsLoan(addMaterialsLoan);
                    } else if ("1".equals(dto.getLoanState())) {
                        // 1.2 开始查询物资柜子，物资柜传的code
                        IsMaterialsCabinet cabinet = iIsMaterialsCabinetService.getOne(Wrappers.<IsMaterialsCabinet>lambdaQuery()
                                .eq(IsMaterialsCabinet::getCabinetCode, dto.getRestitutionToCabinetCode()));
                        Assert.isFalse(cabinet == null, "通过物资柜code:" + dto.getRestitutionToCabinetCode() + "未查询到物资柜信息！");
                        // 4.2开始更新归还记录表
                        ReturnLoanDTO returnLoanDTO = new ReturnLoanDTO();
                        returnLoanDTO.setMaterialsId(materials.getMaterialsId());
                        returnLoanDTO.setRestitutionUserId(userId);
                        returnLoanDTO.setRestitutionToId(cabinet.getCabinetId());
                        iIsMaterialsLoanService.returnIsMaterialsLoan(returnLoanDTO);
                    }
                } catch (Exception e) {
                    log.error("存在异常的存取数据：{}", e);
                    failRfidList.add(dto.getMaterialsRfid());
                }
            }
            // 5.检查有没有异常的物资，如果有，则返回提示
            if (!failRfidList.isEmpty()) {
                return "以下RFID本次存取失败：" + failRfidList;
            }
        }
        return "true";
    }

    @Override
    public List<InstructionVO> getInstructionsList() {
        // 1.获取所有使用说明
        List<IsMaterialsInstructions> instructions = isMaterialsInstructionsService.list();
        ArrayList<InstructionVO> instructionVOS = new ArrayList<>();
        ArrayList<IsMaterialsInstructions> isMaterialsInstructions = new ArrayList<>();
        int allSum = 0;
        if (!instructions.isEmpty()) {
            // 2.有值才有意义，获取所属的物资类型
            List<Long> typeIds = instructions.stream().map(IsMaterialsInstructions::getMaterialsTypeId).distinct().collect(Collectors.toList());
            if (!typeIds.isEmpty()) {
                // 3.查询物资分类数据
                List<IsMaterialsType> isMaterialsTypes = iIsMaterialsTypeService.listByIds(typeIds);
                if (!isMaterialsTypes.isEmpty()) {
                    for (IsMaterialsType isMaterialsType : isMaterialsTypes) {
                        InstructionVO instructionVO = new InstructionVO();
                        instructionVO.setMaterialsTypeId(isMaterialsType.getMaterialsTypeId());
                        instructionVO.setMaterialsTypeName(isMaterialsType.getMaterialsTypeName());
                        instructionVO.setMaterialsTypePicture(isMaterialsType.getMaterialsTypePicture());
                        instructionVO.setMaterialsTypeIcon(isMaterialsType.getMaterialsTypeIcon());
                        List<IsMaterialsInstructions> instructionsList = instructions.stream().filter(o -> o.getMaterialsTypeId().equals(isMaterialsType.getMaterialsTypeId())).collect(Collectors.toList());
                        instructionVO.setInstructions(instructionsList);
                        instructionVO.setNumber(instructionsList.size());
                        allSum = allSum + instructionsList.size();
                        instructionVOS.add(instructionVO);
                        isMaterialsInstructions.addAll(instructionsList);
                    }
                }
            }
        }
        InstructionVO instructionVOAll = new InstructionVO();
        instructionVOAll.setMaterialsTypeId(0L);
        instructionVOAll.setMaterialsTypeName("全部");
        instructionVOAll.setInstructions(isMaterialsInstructions);
        instructionVOAll.setNumber(allSum);
        instructionVOS.add(0, instructionVOAll);
        return instructionVOS;
    }

    @Override
    public CabinetCheckVO getLastCheckPlanByCabinetCode(String cabinetCode) {
        Assert.notBlank(cabinetCode, "请告诉我这是哪台物资柜！");
        // 1.获取物资柜信息
        IsMaterialsCabinet cabinet = iIsMaterialsCabinetService.getOne(Wrappers.<IsMaterialsCabinet>lambdaQuery()
                .eq(IsMaterialsCabinet::getCabinetCode, cabinetCode)
                .orderByDesc(IsMaterialsCabinet::getCabinetId)
                .last("offset 0 rows fetch next 1 rows only"));
        Assert.isFalse(cabinet == null, "物资柜信息不存在！");
        // 2.获取用户信息
        Long userId = SecurityUtils.getUserId();
        // 3.获取这个物资柜当前最近一次未完成的检查计划
        IsMaterialsPlanCabinet planCabinet = iIsMaterialsPlanCabinetService.getOne(Wrappers.<IsMaterialsPlanCabinet>lambdaQuery()
                .eq(IsMaterialsPlanCabinet::getCabinetId, cabinet.getCabinetId())
                .eq(IsMaterialsPlanCabinet::getCheckUserId, userId)
                .ne(IsMaterialsPlanCabinet::getStatus, "1")
                .orderByDesc(IsMaterialsPlanCabinet::getPlanId)
                .last("offset 0 rows fetch next 1 rows only"));
        Assert.isFalse(planCabinet == null, "该物资柜当前无您的检查计划！");
        // 3.1检查当前登陆人的账号是否有检查计划
        IsMaterialsCheckPlan checkPlan = iIsMaterialsCheckPlanService.getOne(Wrappers.<IsMaterialsCheckPlan>lambdaQuery()
                .eq(IsMaterialsCheckPlan::getPlanId, planCabinet.getPlanId())
                .eq(IsMaterialsCheckPlan::getCheckUserId, userId));
        Assert.isFalse(checkPlan == null, "当前物资柜无需您执行的检查计划！");
        // 3.2查询此次检查记录
        List<IsMaterialsCheckRecord> checkRecords = isMaterialsCheckRecordService.list(Wrappers.<IsMaterialsCheckRecord>lambdaQuery()
                .eq(IsMaterialsCheckRecord::getPlanId, planCabinet.getPlanId()));
        List<Long> checkMaterialsIds = null;
        if (!checkRecords.isEmpty()) {
            checkMaterialsIds = checkRecords.stream().map(IsMaterialsCheckRecord::getMaterialsId).collect(Collectors.toList());

        }
        // 4.确实都存在，那就开始查数据了
        // 4.1 开始更新这个检查计划的状态，分为总状态和该物资柜的状态
        // updateCheckPlanStatus(planCabinet, checkPlan);
        // 4.2查询该物资柜的所有物资
        List<IsMaterials> materials = iIsMaterialsService.list(Wrappers.<IsMaterials>lambdaQuery()
                .in(checkMaterialsIds != null && !checkMaterialsIds.isEmpty(), IsMaterials::getMaterialsId, checkMaterialsIds)
                .eq(IsMaterials::getMaterialsCabinetId, cabinet.getCabinetId())
        );
        List<MaterialsCheckVO> materialsCheckVOS = new ArrayList<>();
        if (!materials.isEmpty()) {
            List<Long> typeIds = materials.stream().map(IsMaterials::getMaterialsTypeId).distinct().collect(Collectors.toList());
            if (!typeIds.isEmpty()) {
                List<IsMaterialsType> isMaterialsTypes = iIsMaterialsTypeService.listByIds(typeIds);
                if (!isMaterialsTypes.isEmpty()) {
                    for (IsMaterialsType isMaterialsType : isMaterialsTypes) {
                        // 该分类下所有的物资
                        List<IsMaterials> allMaterials = materials.stream().filter(o -> o.getMaterialsTypeId() != null && o.getMaterialsTypeId().equals(isMaterialsType.getMaterialsTypeId())).collect(Collectors.toList());
                        // 该分类下借出数量
                        int loanNumber = (int) allMaterials.stream().filter(o -> "0".equals(o.getLoanState())).count();
                        // 该分类下待检数量
                        int checkNumber = 0;
                        // 该分类下正常数量
                        Integer normalNumber = null;
                        // 该分类下过期数量
                        Integer timeoutNumber = null;
                        // 该分类下损坏数量
                        Integer badNumber = null;
                        // --获取所有在柜子里的，在柜子需要检查
                        List<IsMaterials> checkMaterials = allMaterials.stream().filter(o -> "1".equals(o.getLoanState())).collect(Collectors.toList());
                        // --查询已经检测的
                        if (!checkMaterials.isEmpty()) {
                            List<Long> checkMaterialIds = checkMaterials.stream().map(IsMaterials::getMaterialsId).collect(Collectors.toList());
                            List<IsMaterialsCheckRecord> checkedMaterials = isMaterialsCheckRecordService.list(Wrappers.<IsMaterialsCheckRecord>lambdaQuery()
                                    .eq(IsMaterialsCheckRecord::getCabinetId, cabinet.getCabinetId())
                                    .eq(IsMaterialsCheckRecord::getPlanId, checkPlan.getPlanId())
                                    .isNotNull(IsMaterialsCheckRecord::getStatus)
                                    .ne(IsMaterialsCheckRecord::getStatus, "")
                                    .in(IsMaterialsCheckRecord::getMaterialsId, checkMaterialIds));
                            int checkedNumber = checkedMaterials.isEmpty() ? 0 : checkedMaterials.size();
                            // --所有的在柜子中的物资 - 这些物资已经在这次计划中检查过的
                            checkNumber = checkMaterials.size() - checkedNumber;
                            // 该分类下正常数量
                            normalNumber = (int) checkedMaterials.stream().filter(o -> "0".equals(o.getStatus())).count();
                            // 该分类下过期数量
                            timeoutNumber = (int) checkedMaterials.stream().filter(o -> "1".equals(o.getStatus()) && "2".equals(o.getReason())).count();
                            // 该分类下损坏数量
                            badNumber = (int) checkedMaterials.stream().filter(o -> "1".equals(o.getStatus()) && "1".equals(o.getReason())).count();
                        }
                        MaterialsCheckVO materialsCheckVO = new MaterialsCheckVO();
                        materialsCheckVO.setMaterialsTypeId(isMaterialsType.getMaterialsTypeId());
                        materialsCheckVO.setMaterialsTypeName(isMaterialsType.getMaterialsTypeName());
                        materialsCheckVO.setMaterialsTypeIcon(isMaterialsType.getMaterialsTypeIcon());
                        materialsCheckVO.setMaterialsTypePicture(isMaterialsType.getMaterialsTypePicture());
                        materialsCheckVO.setAllNumber(allMaterials.size());
                        materialsCheckVO.setLoanNumber(loanNumber);
                        materialsCheckVO.setCheckNumber(checkNumber);
                        materialsCheckVO.setNormalNumber(normalNumber);
                        materialsCheckVO.setTimeoutNumber(timeoutNumber);
                        materialsCheckVO.setBadNumber(badNumber);
                        materialsCheckVOS.add(materialsCheckVO);
                    }
                }
            }
        }
        CabinetCheckVO cabinetCheckVO = new CabinetCheckVO();
        cabinetCheckVO.setPlanId(checkPlan.getPlanId());
        cabinetCheckVO.setPlanName(checkPlan.getPlanName());
        cabinetCheckVO.setPlanDate(checkPlan.getPlanDate());
        cabinetCheckVO.setStatus(checkPlan.getStatus());
        cabinetCheckVO.setSignatureTime(planCabinet.getSignatureTime());
        cabinetCheckVO.setSignatureImg(planCabinet.getSignatureImg());
        cabinetCheckVO.setList(materialsCheckVOS);
        return cabinetCheckVO;
    }

    private Boolean updateCheckPlanStatus(IsMaterialsPlanCabinet planCabinet, IsMaterialsCheckPlan checkPlan) {
        // 1.如果柜子的检查状态是未开始，则更新成进行中
        if (checkPlan.getStatus().equals("0")) {
            iIsMaterialsCheckPlanService.update(Wrappers.<IsMaterialsCheckPlan>lambdaUpdate()
                    .eq(IsMaterialsCheckPlan::getPlanId, checkPlan.getPlanId())
                    .set(IsMaterialsCheckPlan::getStatus, "2"));
            if (planCabinet.getStatus().equals("0")) {
                iIsMaterialsPlanCabinetService.update(Wrappers.<IsMaterialsPlanCabinet>lambdaUpdate()
                        .eq(IsMaterialsPlanCabinet::getPlanId, planCabinet.getPlanId())
                        .eq(IsMaterialsPlanCabinet::getCabinetId, planCabinet.getCabinetId())
                        .set(IsMaterialsPlanCabinet::getStatus, "2"));
            }
        }
        return true;
    }

    @Override
    public CabinetHomePageVO getCabinetHomePage(String cabinetCode) {
        Assert.notBlank(cabinetCode, "请告诉我这是哪台物资柜！");
        // 1.获取物资柜信息
        IsMaterialsCabinet cabinet = iIsMaterialsCabinetService.getOne(Wrappers.<IsMaterialsCabinet>lambdaQuery()
                .eq(IsMaterialsCabinet::getCabinetCode, cabinetCode)
                .orderByDesc(IsMaterialsCabinet::getCabinetId)
                .last("offset 0 rows fetch next 1 rows only"));
        Assert.isFalse(cabinet == null, "物资柜信息不存在！");
        // 1.1柜子中的物资信息
        List<IsMaterials> isMaterials = iIsMaterialsService.list(Wrappers.<IsMaterials>lambdaQuery()
                .eq(IsMaterials::getMaterialsCabinetId, cabinet.getCabinetId()));
        // 2.获取用户信息
        Long userId = SecurityUtils.getUserId();
        // 3.获取本人在该物资柜子上有效取还数据
        Integer rarNumber = null;
        if (isMaterials.isEmpty()) {
            rarNumber = 0;
        } else {
            List<Long> materialsIds = isMaterials.stream()
                    .filter(o -> StringUtils.isNotBlank(o.getLoanState()) && o.getLoanState().equals("0"))
                    .map(IsMaterials::getMaterialsId).collect(Collectors.toList());
            if (!materialsIds.isEmpty()) {
                List<IsMaterialsLoan> loanList = iIsMaterialsLoanService.list(Wrappers.<IsMaterialsLoan>lambdaQuery()
                        .in(IsMaterialsLoan::getMaterialsId, materialsIds)
                        .eq(IsMaterialsLoan::getLoanFromId, cabinet.getCabinetId())
                        .eq(IsMaterialsLoan::getLoanUserId, userId)
                        .ne(IsMaterialsLoan::getStatus, "1"));
                if (!loanList.isEmpty()) {
                    rarNumber = loanList.size();
                }
            }
        }
        // 4.获取该物资柜的需要更换数量，在柜子里，损坏或者过期
        int changeNumber = (int) isMaterials.stream().filter(o ->
                StringUtils.isNotBlank(o.getLoanState()) && StringUtils.isNotBlank(o.getStatus()) && (o.getStatus().equals("1") || o.getStatus().equals("2"))
        ).count();
        // 5.获取本人在该物资柜上未完成的检查计划
        Integer checkNumber = null;
        /*List<IsMaterialsPlanCabinet> planCabinets = iIsMaterialsPlanCabinetService.list(Wrappers.<IsMaterialsPlanCabinet>lambdaQuery()
                .eq(IsMaterialsPlanCabinet::getCabinetId, cabinet.getCabinetId())
                .isNull(IsMaterialsPlanCabinet::getSignatureImg)
                .isNull(IsMaterialsPlanCabinet::getSignatureTime));
        if (!planCabinets.isEmpty()) {
            List<Long> planIds = planCabinets.stream().map(IsMaterialsPlanCabinet::getPlanId).distinct().collect(Collectors.toList());
            List<IsMaterialsCheckPlan> myCheckPlans = iIsMaterialsCheckPlanService.list(Wrappers.<IsMaterialsCheckPlan>lambdaQuery()
                    .eq(IsMaterialsCheckPlan::getCheckUserId, userId)
                    .in(IsMaterialsCheckPlan::getPlanId, planIds)
                    .eq(IsMaterialsCheckPlan::getStatus, "0"));
            if (!myCheckPlans.isEmpty()) {
                checkNumber = myCheckPlans.size();
            }
        }*/
        List<IsMaterialsPlanCabinet> myNotFinishPlans = iIsMaterialsPlanCabinetService.list(Wrappers.<IsMaterialsPlanCabinet>lambdaQuery()
                .eq(IsMaterialsPlanCabinet::getCheckUserId, userId)
                .eq(IsMaterialsPlanCabinet::getCabinetId, cabinet.getCabinetId())
                .ne(IsMaterialsPlanCabinet::getSubmit, "1")
                .ne(IsMaterialsPlanCabinet::getStatus, "1"));
        if (!myNotFinishPlans.isEmpty()) {
            checkNumber = 1;
        }
        // 6.获取物资分类下的可借数据
        List<MaterialsHomeVO> materialsHomeVOS = new ArrayList<>();
        List<IsMaterials> materials = iIsMaterialsService.list(Wrappers.<IsMaterials>lambdaQuery()
                .eq(IsMaterials::getMaterialsCabinetId, cabinet.getCabinetId()));
        if (!materials.isEmpty()) {
            List<Long> typeIds = materials.stream().map(IsMaterials::getMaterialsTypeId).distinct().collect(Collectors.toList());
            if (!typeIds.isEmpty()) {
                List<IsMaterialsType> isMaterialsTypes = iIsMaterialsTypeService.listByIds(typeIds);
                if (!isMaterialsTypes.isEmpty()) {
                    for (IsMaterialsType isMaterialsType : isMaterialsTypes) {
                        MaterialsHomeVO materialsHomeVO = new MaterialsHomeVO();
                        materialsHomeVO.setMaterialsTypeId(isMaterialsType.getMaterialsTypeId());
                        materialsHomeVO.setMaterialsTypeName(isMaterialsType.getMaterialsTypeName());
                        materialsHomeVO.setMaterialsTypeIcon(isMaterialsType.getMaterialsTypeIcon());
                        materialsHomeVO.setMaterialsTypePicture(isMaterialsType.getMaterialsTypePicture());
                        List<IsMaterials> allMaterials = materials.stream().filter(o -> o.getMaterialsTypeId() != null && o.getMaterialsTypeId().equals(isMaterialsType.getMaterialsTypeId())).collect(Collectors.toList());
                        materialsHomeVO.setAllNumber(allMaterials.size());
                        int borrowableNumber = (int) allMaterials.stream().filter(o -> "1".equals(o.getLoanState()) && "0".equals(o.getStatus())).count();
                        materialsHomeVO.setBorrowableNumber(borrowableNumber);
                        materialsHomeVOS.add(materialsHomeVO);
                    }
                }
            }
        }
        CabinetHomePageVO cabinetHomePageVO = new CabinetHomePageVO();
        cabinetHomePageVO.setRarNumber(rarNumber);
        cabinetHomePageVO.setCheckNumber(checkNumber);
        cabinetHomePageVO.setChangeNumber(changeNumber);
        cabinetHomePageVO.setList(materialsHomeVOS);
        return cabinetHomePageVO;
    }

    @Override
    public MaterialsCheckInitVO getCheckMaterialsByCabinetCode(String cabinetCode, Long planId) {
        Assert.notBlank(cabinetCode, "cabinetCode不能为空!");
        Assert.notNull(planId, "检查计划planId不能为空!");
        IsMaterialsCabinet cabinet = iIsMaterialsCabinetService.getOne(Wrappers.<IsMaterialsCabinet>lambdaQuery()
                .eq(IsMaterialsCabinet::getCabinetCode, cabinetCode));
        Assert.isFalse(cabinet == null, "物资柜信息不存在！");
        MaterialsCheckInitVO materialsCheckInitVO = new MaterialsCheckInitVO();
        // 检查此次数据是否初始化，初始化了，就不用生成直接查
        List<IsMaterialsCheckRecord> checkRecords = isMaterialsCheckRecordService.getCheckMaterialsByCabinetCode(planId, cabinet.getCabinetId());
        ArrayList<IsMaterialsCheckRecord> checkRecordArrayList = new ArrayList<>();
        List<CheckMaterialsDateVO> vos = iIsMaterialsService.getCheckMaterialsByCabinetId(cabinet.getCabinetId());
        if (!checkRecords.isEmpty()) {
            materialsCheckInitVO.setList(checkRecords);
        } else {
            for (CheckMaterialsDateVO vo : vos) {
                IsMaterialsCheckRecord checkRecord = new IsMaterialsCheckRecord();
                checkRecord.setPlanId(planId);
                checkRecord.setCabinetId(cabinet.getCabinetId());
                checkRecord.setMaterialsId(vo.getMaterialsId());
                checkRecord.setCheckUserId(SecurityUtils.getUserId());
                checkRecord.setCheckDate(new Date());
                checkRecord.setMaterialsRfid(vo.getMaterialsRfid());
                checkRecord.setMaterialsTypeIcon(vo.getMaterialsTypeIcon());
                checkRecord.setMaterialsTypePicture(vo.getMaterialsTypePicture());
                checkRecord.setMaterialsTypeName(vo.getMaterialsTypeName());
                checkRecord.setMaterialsName(vo.getMaterialsName());
                checkRecordArrayList.add(checkRecord);
                isMaterialsCheckRecordService.save(checkRecord);
            }
            materialsCheckInitVO.setList(checkRecordArrayList);
        }

        // 查询物资检查标准
        Set<CheckStandardVO> sets = new HashSet<>();
        for (CheckMaterialsDateVO vo : vos) {
            CheckStandardVO checkStandardVO = new CheckStandardVO();
            checkStandardVO.setMaterialsTypeId(vo.getMaterialsTypeId());
            checkStandardVO.setMaterialsTypeName(vo.getMaterialsTypeName());
            checkStandardVO.setMaterialsTypeIcon(vo.getMaterialsTypeIcon());
            checkStandardVO.setMaterialsTypePicture(vo.getMaterialsTypePicture());
            checkStandardVO.setCheckStandard(vo.getCheckStandard());
            sets.add(checkStandardVO);
        }
        materialsCheckInitVO.setStandards(new ArrayList<>(sets));
        // 获取下方检查统计
        CheckProgressVO checkProgressVO = new CheckProgressVO();
        checkProgressVO.setCheckNum(0);
        checkProgressVO.setNormalNum(0);
        checkProgressVO.setTimeOutNum(0);
        checkProgressVO.setBadNum(0);
        if (checkRecords.isEmpty()) {
            checkProgressVO.setCheckNum(materialsCheckInitVO.getList().size());
        } else {
            int checkNum = (int) checkRecords.stream().filter(o -> StringUtils.isBlank(o.getStatus())).count();
            int normalNum = (int) checkRecords.stream().filter(o -> StringUtils.isNotBlank(o.getStatus()) && "0".equals(o.getStatus())).count();
            int timeOutNum = (int) checkRecords.stream().filter(o -> StringUtils.isNotBlank(o.getStatus()) && "1".equals(o.getStatus())
                    && "2".equals(o.getReason())).count();
            int badNum = (int) checkRecords.stream().filter(o -> StringUtils.isNotBlank(o.getStatus()) && "1".equals(o.getStatus())
                    && "1".equals(o.getReason())).count();
            checkProgressVO.setCheckNum(checkNum);
            checkProgressVO.setNormalNum(normalNum);
            checkProgressVO.setTimeOutNum(timeOutNum);
            checkProgressVO.setBadNum(badNum);
        }
        materialsCheckInitVO.setCheckProgressVO(checkProgressVO);
        return materialsCheckInitVO;
    }

    @Override
    public Boolean insertCheckRecord(CheckParamDTO dto) {
        if (!dto.getList().isEmpty()) {
            Long userId = SecurityUtils.getUserId();
            // 0.检查是否已经提交，如果已经提交则不允许再次提交
            List<Long> cabinetIds = dto.getList().stream().map(IsMaterialsCheckRecord::getCabinetId).distinct().collect(Collectors.toList());
            Assert.isFalse(cabinetIds.isEmpty(), "物资柜不能为空！");
            Assert.notNull(dto.getList().get(0).getPlanId(), "检查计划ID不能为空！");
            List<IsMaterialsPlanCabinet> list1 = iIsMaterialsPlanCabinetService.list(Wrappers.<IsMaterialsPlanCabinet>lambdaQuery()
                    .eq(IsMaterialsPlanCabinet::getPlanId, dto.getList().get(0).getPlanId())
                    .in(IsMaterialsPlanCabinet::getCabinetId, cabinetIds)
                    .eq(IsMaterialsPlanCabinet::getSubmit, "1"));
            Assert.isTrue(list1.isEmpty(), "存在重复提交检查记录，请检查！");

            for (IsMaterialsCheckRecord isMaterialsCheckRecord : dto.getList()) {
                Assert.notNull(isMaterialsCheckRecord.getRecordId(), "记录id不能为空!");
                isMaterialsCheckRecord.setCheckDate(new Date());
                isMaterialsCheckRecord.setCheckUserId(userId);
                isMaterialsCheckRecordService.updateById(isMaterialsCheckRecord);
            }
        }
        return true;
    }

    @Transactional
    @Override
    public Boolean insertSubmitPlan(SubmitPlanDTO dto) {
        Assert.notNull(dto.getPlanId(), "计划id不能空！");
        Assert.notBlank(dto.getCabinetCode(), "物资柜code不能为空！");
        IsMaterialsCabinet cabinetByCode = iIsMaterialsCabinetService.getCabinetByCode(dto.getCabinetCode());
        Assert.isFalse(cabinetByCode == null, "物资柜信息不存在！");
        // 1.检查初始化的物资检查数据有没有检查完毕
        List<IsMaterialsCheckRecord> list = isMaterialsCheckRecordService.list(Wrappers.<IsMaterialsCheckRecord>lambdaQuery()
                .eq(IsMaterialsCheckRecord::getCabinetId, cabinetByCode.getCabinetId())
                .eq(IsMaterialsCheckRecord::getPlanId, dto.getPlanId()));
        Assert.isFalse(list.isEmpty(), "暂无检查数据需要提交！");
        List<IsMaterialsCheckRecord> collect = list.stream().filter(o -> o.getStatus() == null || StringUtils.isBlank(o.getStatus())).collect(Collectors.toList());
        Assert.isTrue(collect.isEmpty(), "存在未检查的物资，请重新盘查！");
        // 2.检查签名是否上传
        IsMaterialsPlanCabinet one = iIsMaterialsPlanCabinetService.getOne(Wrappers.<IsMaterialsPlanCabinet>lambdaQuery()
                .eq(IsMaterialsPlanCabinet::getCabinetId, cabinetByCode.getCabinetId())
                .eq(IsMaterialsPlanCabinet::getPlanId, dto.getPlanId()));
        Assert.notBlank(one.getSignatureImg(), "您的签名暂未上传，不可提交！");
        // 3.都完事了，开始更新物资的状态，该物资柜的提交状态，物资计划的状态
        for (IsMaterialsCheckRecord checkRecord : list) {
            // 3.1.开始更新物资本身状态
            if ("1".equals(checkRecord.getStatus()) && StringUtils.isNotBlank(checkRecord.getReason())) {
                //  reason字典值exceptions_status 对应调整material_info_status  损坏和过期时对应的，所以直接set
                iIsMaterialsService.update(Wrappers.<IsMaterials>lambdaUpdate()
                        .eq(IsMaterials::getMaterialsId, checkRecord.getMaterialsId())
                        .set(IsMaterials::getStatus, checkRecord.getReason()));
            } else {
                iIsMaterialsService.update(Wrappers.<IsMaterials>lambdaUpdate()
                        .eq(IsMaterials::getMaterialsId, checkRecord.getMaterialsId())
                        .set(IsMaterials::getStatus, "0"));
            }
        }
        // 4.提交该物资柜的提交状态
        iIsMaterialsPlanCabinetService.update(Wrappers.<IsMaterialsPlanCabinet>lambdaUpdate()
                .eq(IsMaterialsPlanCabinet::getCabinetId, cabinetByCode.getCabinetId())
                .eq(IsMaterialsPlanCabinet::getPlanId, dto.getPlanId())
                .set(IsMaterialsPlanCabinet::getSubmit, "1")
                .set(IsMaterialsPlanCabinet::getStatus, "1")
        );
        // 5.检查此次计划所有的物资柜是不是都提交了，如果都提交了，则可以直接更新计划完成
        List<IsMaterialsPlanCabinet> list1 = iIsMaterialsPlanCabinetService.list(Wrappers.<IsMaterialsPlanCabinet>lambdaQuery()
                .eq(IsMaterialsPlanCabinet::getPlanId, dto.getPlanId())
                .ne(IsMaterialsPlanCabinet::getStatus, "1"));
        if (list1.isEmpty()) {
            iIsMaterialsCheckPlanService.update(Wrappers.<IsMaterialsCheckPlan>lambdaUpdate()
                    .eq(IsMaterialsCheckPlan::getPlanId, dto.getPlanId())
                    .set(IsMaterialsCheckPlan::getStatus, "1"));
        }
        return true;
    }

    @Override
    public Boolean insertSign(SignDTO dto) {
        Assert.notBlank(dto.getCabinetCode(), "物资柜code不能为空!");
        Assert.notNull(dto.getPlanId(), "计划id不能为空!");
        Assert.notBlank(dto.getSignatureImg(), "签名不能为空!");
        IsMaterialsCabinet cabinet = iIsMaterialsCabinetService.getOne(Wrappers.<IsMaterialsCabinet>lambdaQuery()
                .eq(IsMaterialsCabinet::getCabinetCode, dto.getCabinetCode()));
        Assert.isFalse(cabinet == null, "物资柜信息不存在！");
        /*IsMaterialsPlanCabinet one = iIsMaterialsPlanCabinetService.getOne(Wrappers.<IsMaterialsPlanCabinet>lambdaQuery()
                .eq(IsMaterialsPlanCabinet::getPlanId, dto.getPlanId())
                .eq(IsMaterialsPlanCabinet::getCabinetId, cabinet.getCabinetId()));
        Assert.isFalse(StringUtils.isNoneBlank(one.getSignatureImg()), "您已签名，请勿重复！");*/
        iIsMaterialsPlanCabinetService.update(Wrappers.<IsMaterialsPlanCabinet>lambdaUpdate()
                .eq(IsMaterialsPlanCabinet::getPlanId, dto.getPlanId())
                .eq(IsMaterialsPlanCabinet::getCabinetId, cabinet.getCabinetId())
                .set(IsMaterialsPlanCabinet::getSignatureImg, dto.getSignatureImg())
                .set(IsMaterialsPlanCabinet::getSignatureTime, new Date()));
        return true;
    }

    @Override
    public AutoReplaceReportVO insertAutoChange(AutoChangeDTO dto) {
        Assert.notBlank(dto.getCabinetCode(), "物资柜CODE不能为空!");
        IsMaterialsCabinet cabinetByCode = iIsMaterialsCabinetService.getCabinetByCode(dto.getCabinetCode());
        // 0.构造记录的集合
        List<IsMaterialsChangeRecord> isMaterialsChangeRecords = new ArrayList<>();
        Long userId = SecurityUtils.getUserId();
        Date date = new Date();
        List<IsMaterials> unbingdingList = new ArrayList<>();
        List<IsMaterials> bingdingList = new ArrayList<>();
        // 1.开始解绑
        if (!dto.getUnbindMaterialRfidList().isEmpty()) {
            iIsMaterialsService.update(Wrappers.<IsMaterials>lambdaUpdate()
                    .in(IsMaterials::getMaterialsRfid, dto.getUnbindMaterialRfidList())
                    .set(IsMaterials::getMaterialsCabinetId, null)
                    .set(IsMaterials::getLoanState, "0"));
            unbingdingList = iIsMaterialsService.getMaterialListByRfid(dto.getUnbindMaterialRfidList());
            for (IsMaterials materials : unbingdingList) {
                IsMaterialsChangeRecord isMaterialsChangeRecord = new IsMaterialsChangeRecord();
                isMaterialsChangeRecord.setOldMaterialsId(materials.getMaterialsId());
                isMaterialsChangeRecord.setOldMaterialsRfid(materials.getMaterialsRfid());
                isMaterialsChangeRecord.setChangeUserId(userId);
                isMaterialsChangeRecord.setChangeDate(date);
                isMaterialsChangeRecord.setChangeType("1");
                isMaterialsChangeRecord.setOperateType("0");
                isMaterialsChangeRecords.add(isMaterialsChangeRecord);
            }
        }
        // 2.开始绑定
        if (!dto.getBindingMaterialRfidList().isEmpty()) {
            // 判定绑定的物资数据是否存在，存在的话是不是异常的数据
            iIsMaterialsService.update(Wrappers.<IsMaterials>lambdaUpdate()
                    .in(IsMaterials::getMaterialsRfid, dto.getBindingMaterialRfidList())
                    .set(IsMaterials::getMaterialsCabinetId, cabinetByCode.getCabinetId())
                    .set(IsMaterials::getLoanState, "1"));
                    // .set(IsMaterials::getStatus, "0"));
            bingdingList = iIsMaterialsService.getMaterialListByRfid(dto.getBindingMaterialRfidList());
            // Assert.isFalse(bingdingList.size() != dto.getBindingMaterialRfidList().size(), "缺邵需要绑定的物资");
            for (IsMaterials materials : bingdingList) {
                Assert.isTrue(materials.getStatus().equals("0"), "存在异常的替换物资！");
                IsMaterialsChangeRecord isMaterialsChangeRecord = new IsMaterialsChangeRecord();
                isMaterialsChangeRecord.setNewMaterialsId(materials.getMaterialsId());
                isMaterialsChangeRecord.setNewMaterialsRfid(materials.getMaterialsRfid());
                isMaterialsChangeRecord.setChangeUserId(userId);
                isMaterialsChangeRecord.setChangeDate(date);
                isMaterialsChangeRecord.setChangeType("1");
                isMaterialsChangeRecord.setOperateType("1");
                isMaterialsChangeRecords.add(isMaterialsChangeRecord);
                // 处理绑定入柜的物资的借取记录
                iIsMaterialsLoanService.update(Wrappers.<IsMaterialsLoan>lambdaUpdate()
                        .eq(IsMaterialsLoan::getMaterialsId, materials.getMaterialsId())
                        .set(IsMaterialsLoan::getRestitutionUserId, SecurityUtils.getUserId())
                        .set(IsMaterialsLoan::getActualRestitutionTime, new Date())
                        .set(IsMaterialsLoan::getStatus, "1"));
                // 处理归还异常
                isMaterialsLoanExceptionService.update(Wrappers.<IsMaterialsLoanException>lambdaUpdate()
                        .eq(IsMaterialsLoanException::getMaterialsId, materials.getMaterialsId())
                        .set(IsMaterialsLoanException::getRestitutionUserId, SecurityUtils.getUserId())
                        .set(IsMaterialsLoanException::getHandleTime, new Date())
                        .set(IsMaterialsLoanException::getStatus, "1"));
            }
        }
        // 3.如果有数据则插入
        if (!isMaterialsChangeRecords.isEmpty()) {
            // isMaterialsChangeRecordService.saveBatch(isMaterialsChangeRecords);
            for (IsMaterialsChangeRecord isMaterialsChangeRecord : isMaterialsChangeRecords) {
                isMaterialsChangeRecordService.save(isMaterialsChangeRecord);
            }
        }
        // 4.开始整理此次的总结
        AutoReplaceReportVO autoReplaceReportVO = new AutoReplaceReportVO();
        autoReplaceReportVO.setCreateTime(date);
        autoReplaceReportVO.setNikeName(SecurityUtils.getLoginUser().getUser().getNickName());
        // 4.1放入物资
        List<AutoReplaceMaterialVO> bindingMaterialVOS = new ArrayList<>();
        if (!bingdingList.isEmpty()) {
            for (IsMaterials materials : bingdingList) {
                AutoReplaceMaterialVO autoReplaceMaterialVO = new AutoReplaceMaterialVO();
                autoReplaceMaterialVO.setMaterialsName(materials.getMaterialsName());
                autoReplaceMaterialVO.setMaterialsTypeIcon(materials.getMaterialsTypeIcon());
                autoReplaceMaterialVO.setMaterialsTypePicture(materials.getMaterialsTypePicture());
                autoReplaceMaterialVO.setMaterialsRfid(materials.getMaterialsRfid());
                autoReplaceMaterialVO.setStatus(materials.getStatus());
                bindingMaterialVOS.add(autoReplaceMaterialVO);
            }
        }
        autoReplaceReportVO.setBindingList(bindingMaterialVOS);
        // 4.2取出物资
        List<AutoReplaceMaterialVO> unbindingMaterialVOS = new ArrayList<>();
        if (!unbingdingList.isEmpty()) {
            for (IsMaterials materials : unbingdingList) {
                AutoReplaceMaterialVO autoReplaceMaterialVO = new AutoReplaceMaterialVO();
                autoReplaceMaterialVO.setMaterialsName(materials.getMaterialsName());
                autoReplaceMaterialVO.setMaterialsTypeIcon(materials.getMaterialsTypeIcon());
                autoReplaceMaterialVO.setMaterialsTypePicture(materials.getMaterialsTypePicture());
                autoReplaceMaterialVO.setMaterialsRfid(materials.getMaterialsRfid());
                autoReplaceMaterialVO.setStatus(materials.getStatus());
                unbindingMaterialVOS.add(autoReplaceMaterialVO);
            }
        }
        autoReplaceReportVO.setUnbindingList(unbindingMaterialVOS);
        // 更新检查记录
        iIsMaterialsPlanCabinetService.autoChangeCheckRecord(dto.getCabinetCode());
        return autoReplaceReportVO;
    }

    @Override
    public Boolean startCheckPlan(StartCheckPlanDTO dto) {
        Assert.notNull(dto.getPlanId(), "planId不可为空！");
        Assert.notBlank(dto.getCabinetCode(), "物资柜code不可为空！");
        IsMaterialsCabinet cabinetByCode = iIsMaterialsCabinetService.getCabinetByCode(dto.getCabinetCode());
        Assert.isTrue(cabinetByCode != null, dto.getCabinetCode() + "物资柜不存在！");
        IsMaterialsCheckPlan checkPlan = iIsMaterialsCheckPlanService.getOne(Wrappers.<IsMaterialsCheckPlan>lambdaQuery()
                .eq(IsMaterialsCheckPlan::getPlanId, dto.getPlanId()));
        IsMaterialsPlanCabinet planCabinet = iIsMaterialsPlanCabinetService.getOne(Wrappers.<IsMaterialsPlanCabinet>lambdaQuery()
                .eq(IsMaterialsPlanCabinet::getPlanId, dto.getPlanId())
                .eq(IsMaterialsPlanCabinet::getCabinetId, cabinetByCode.getCabinetId()));

        // 1.如果柜子的检查状态是未开始，则更新成进行中
        if (checkPlan.getStatus().equals("0")) {
            iIsMaterialsCheckPlanService.update(Wrappers.<IsMaterialsCheckPlan>lambdaUpdate()
                    .eq(IsMaterialsCheckPlan::getPlanId, checkPlan.getPlanId())
                    .set(IsMaterialsCheckPlan::getStatus, "2"));
            if (planCabinet.getStatus().equals("0")) {
                iIsMaterialsPlanCabinetService.update(Wrappers.<IsMaterialsPlanCabinet>lambdaUpdate()
                        .eq(IsMaterialsPlanCabinet::getPlanId, planCabinet.getPlanId())
                        .eq(IsMaterialsPlanCabinet::getCabinetId, planCabinet.getCabinetId())
                        .set(IsMaterialsPlanCabinet::getStatus, "2"));
            }
        }
        return true;
    }
}
