package com.junmp.v2.channel.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.junmp.jyzb.api.bean.dto.ChannelDto.*;
import com.junmp.jyzb.api.bean.query.inAndOutRecordReq.DetailJsonReq;
import com.junmp.jyzb.api.bean.req.ChannelReq.*;
import com.junmp.jyzb.api.bean.vo.ChannelVo.ChannelShelfInventoryVo;
import com.junmp.jyzb.api.bean.vo.ChannelVo.EquipmentShelfPositionVo;
import com.junmp.jyzb.api.exception.JYZBAppException;
import com.junmp.jyzb.api.exception.enums.JyzbV2ExceptionEnum;
import com.junmp.jyzb.cache.OutInRecordRedisCache;
import com.junmp.jyzb.entity.Package;
import com.junmp.jyzb.entity.*;
import com.junmp.jyzb.mapper.InventoryMapper;
import com.junmp.jyzb.service.*;
import com.junmp.jyzb.utils.DateTimeUtil;
import com.junmp.jyzb.utils.RedisUtils;
import com.junmp.v2.channel.mapper.ChannelMapper;
import com.junmp.v2.channel.service.ChannelService;
import com.junmp.v2.file.api.bean.req.SysFileInfoReq;
import com.junmp.v2.file.api.bean.res.SysFileInfoResp;
import com.junmp.v2.file.biz.service.SysFileInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <pre>
 *
 * 描述：
 * 版本：1.0.0
 * 日期：2024/9/6 上午9:07
 * 作者：xuzc@junmp.com.cn
 * <br>修改记录
 * <br>修改日期 修改人 修改内容
 *
 * </pre>
 */
@Service
public class ChannelServiceImpl implements ChannelService
{
    @Resource
    private WarehouseService warehouseService;
    @Resource
    private PubOrgService pubOrgService;
    @Resource
    private PolicemanService policemanService;
    @Resource
    private PoliceFingerService policeFingerService;
    @Resource
    private DeviceConfigService deviceConfigService;
    @Resource
    private ShelfService shelfService;
    @Resource
    private InventoryService inventoryService;
    @Resource
    private EquipmentTypeService equipmentTypeService;
    @Resource
    private PackageService packageService;
    @Resource
    private PackageInformationService packageInformationService;
    @Resource
    private InventoryBoxMarkService inventoryBoxMarkService;
    @Resource
    private SysFileInfoService sysFileInfoService;
    @Resource
    private OrderMainService orderMainService;
    @Resource
    private OrderDetailService orderDetailService;
    @Resource
    private PrintEpcsService printEpcsService;
    @Resource
    private OutInRecordRedisCache outInRecordRedisCache;
    @Resource
    private LogSummaryService logSummaryService;
    @Resource
    private LogDetailService logDetailService;
    @Resource
    private WarehouseInventoryService warehouseInventoryService;
    @Resource
    private InventorySummaryService inventorySummaryService;

    @Resource
    private ChannelMapper channelMapper;

    @Autowired
    private RedisUtils redisUtils;

    @Resource
    private InventoryMapper inventoryMapper;

    @Override
    public List<ChannelWarehouseDto> GetListWarehouse(GetListWarehouseReq req)
    {
        //本级及下级组织机构获取
        Map<Long, String> orgList = new HashMap<>();
        if(StrUtil.isNotBlank(req.getOrgizationId())) {
            List<PubOrg> orgs = pubOrgService.list();

            //是否存在组织机构
            Optional<PubOrg> thisOrg = orgs.stream().filter(s -> s.getOrgId().equals(Long.parseLong(req.getOrgizationId()))).findFirst();

            //存储ID--名称键值对
            if(thisOrg.isPresent()) {
                orgList = orgs.stream()
                        .filter(s -> s.getOrgParentIds().contains(req.getOrgizationId()))
                        .collect(Collectors.toMap(PubOrg::getOrgId, PubOrg::getOrgName));
                orgList.put(thisOrg.get().getOrgId(), thisOrg.get().getOrgName());
            }
        }

        //查询仓库
        List<Warehouse> warehouses = warehouseService.list(new LambdaQueryWrapper<Warehouse>()
                .in(CollectionUtil.isNotEmpty(orgList), Warehouse::getOrgIdInt, orgList.keySet())
                .like(StrUtil.isNotBlank(req.getName()), Warehouse::getName, req.getName()));

        List<ChannelWarehouseDto> Dtos = new ArrayList<>();

        for (Warehouse warehouse : warehouses) {
            Dtos.add(new ChannelWarehouseDto(
                    warehouse.getId(),
                    1,
                    warehouse.getName(),
                    warehouse.getLocation(),
                    warehouse.getLocation(),
                    warehouse.getOrgIdInt().toString(),
                    orgList.containsKey(warehouse.getOrgIdInt()) ? orgList.get(warehouse.getOrgIdInt()) : "",
                    warehouse.getPhone(),
                    warehouse.getCreateTime(),
                    warehouse.getUpdateTime(),
                    warehouse.getUpdateUser(),
                    warehouse.getIsLocked() == 1,
                    warehouse.getVideo()
            ));
        }
        return Dtos;
    }

    @Override
    public List<ChannelWarehouseDto> GetListOrgWarehouse(GetListWarehouseReq req)
    {
        //是否存在组织机构
        PubOrg org = pubOrgService.getOne(new LambdaQueryWrapper<PubOrg>().eq(PubOrg::getOrgId, req.getOrgizationId()));
        if (org == null){
            throw new JYZBAppException(JyzbV2ExceptionEnum.ORGANIZATION_ERROR);
        }

        List<Warehouse> warehouses = warehouseService.list(new LambdaQueryWrapper<Warehouse>()
                .eq(Warehouse::getOrgIdInt, req.getOrgizationId()));

        List<ChannelWarehouseDto> Dtos = new ArrayList<>();

        for (Warehouse warehouse : warehouses) {
            Dtos.add(new ChannelWarehouseDto(
                    warehouse.getId(),
                    1,
                    warehouse.getName(),
                    warehouse.getLocation(),
                    warehouse.getLocation(),
                    warehouse.getOrgIdInt().toString(),
                    org.getOrgName(),
                    warehouse.getPhone(),
                    warehouse.getCreateTime(),
                    warehouse.getUpdateTime(),
                    warehouse.getUpdateUser(),
                    warehouse.getIsLocked() == 1,
                    warehouse.getVideo()
            ));
        }

        return Dtos;
    }

    @Override
    public List<ChannelPoliceDto> GetOrgStaff(GetOrgStaffReq req)
    {
        if (ObjectUtil.isEmpty(req.getOrgId())){
            throw new JYZBAppException(JyzbV2ExceptionEnum.ORGID_ERROR);
        }
        List<Policeman> policemans = policemanService.list(new LambdaQueryWrapper<Policeman>().eq(Policeman::getOrgId, req.getOrgId()));

        if(CollectionUtil.isEmpty(policemans)){
            return Collections.emptyList();
        }

        List<String> policeIds = policemans.stream().map(Policeman::getId).collect(Collectors.toList());

        List<PoliceFinger> fingers = policeFingerService.list(new LambdaQueryWrapper<PoliceFinger>().in(PoliceFinger::getPoliceId, policeIds));

        List<ChannelPoliceDto> rs = new ArrayList<>();
        for (Policeman policeman : policemans) {
            rs.add(new ChannelPoliceDto(
                    policeman.getId(),
                    policeman.getName(),
                    policeman.getPoliceCode(),
                    policeman.getPhoto(),
                    policeman.getUpdateTime(),
                    policeman.getCreateTime(),
                    fingers.stream()
                            .filter(s -> s.getPoliceId() == policeman.getId())
                            .map(s -> new ChannelPoliceFingerDto(s.getFingerNum(),s.getFingerInfo()))
                            .collect(Collectors.toList())
            ));
        }

        return rs;
    }

    @Override
    public ChannelConfigDto GetCfgByNumV2(GetCfgByNumV2Req req)
    {
        if (ObjectUtil.isEmpty(req.getCode())){
            throw new JYZBAppException(JyzbV2ExceptionEnum.CODE_ERROR);
        }
        DeviceConfig config = deviceConfigService.getOne(new LambdaQueryWrapper<DeviceConfig>()
                .eq(DeviceConfig::getDeviceType, 0)
                .eq(DeviceConfig::getDeviceCode, req.getCode()));

        if(config == null){
            return new ChannelConfigDto();
        }

        ChannelConfigDto rs = JSON.parseObject(config.getDeviceConfig(), ChannelConfigDto.class);

        return rs;
    }

    @Override
    public ChannelPoliceCardNoDto GetPoliceByCardNo(GetPoliceByCardNoReq req)
    {
        if (ObjectUtil.isEmpty(req.getCardNo())){
            throw new JYZBAppException(JyzbV2ExceptionEnum.CARDNO_ERROR);
        }
        Policeman police = policemanService.getOne(new LambdaQueryWrapper<Policeman>()
                .eq(Policeman::getPoliceCode, req.getCardNo())
                .eq(StrUtil.isNotBlank(req.getOrgId()), Policeman::getOrgId, req.getOrgId()));

        if(police == null){
            throw new JYZBAppException(JyzbV2ExceptionEnum.POLICE_ERROR);
        }

        return new ChannelPoliceCardNoDto(police.getName(), police.getId(), police.getOrgId().toString());
    }

    @Override
    public List<ChannelShelfDto> GetListShelf(GetShelfReq req)
    {
        List<Shelf> shelfs = shelfService.list(new LambdaQueryWrapper<Shelf>()
                .eq(StrUtil.isNotBlank(req.getWarehouseId()), Shelf::getWarehouseId, req.getWarehouseId())
                .like(StrUtil.isNotBlank(req.getName()), Shelf::getShelfName, req.getName()));

        if(CollectionUtil.isEmpty(shelfs)){
            return Collections.emptyList();
        }

        //获取仓库信息
        List<String> warehouseIds = shelfs.stream()
                .map(Shelf::getWarehouseId).collect(Collectors.toList());
        Map<String, Warehouse> warehouseMap = warehouseService.list(
                new LambdaQueryWrapper<Warehouse>().in(Warehouse::getId, warehouseIds)
                )
                .stream().collect(Collectors.toMap(s -> s.getId(), s -> s));

        List<ChannelShelfDto> dtos = new ArrayList<>();
        for(Shelf shelf : shelfs){
            Warehouse thisWarehouse = warehouseMap.get(shelf.getWarehouseId());
            dtos.add(new ChannelShelfDto(
                    shelf.getShelfId(),
                    shelf.getCreateTime(),
                    shelf.getShelfName(),
                    shelf.getCode(),
                    shelf.getType(),
                    shelf.getWarehouseId(),
                    shelf.getSizeInfo(),
                    shelf.getShelfRanges(),
                    shelf.getShelfRows(),
                    shelf.getShelfColumns(),
                    shelf.getUrl(),
                    thisWarehouse == null ?
                            null :
                            new ChannelWarehouseDto(
                                    thisWarehouse.getId(),
                                    1,
                                    thisWarehouse.getName(),
                                    thisWarehouse.getLocation(),
                                    thisWarehouse.getLocation(),
                                    thisWarehouse.getOrgIdInt().toString(),
                                    thisWarehouse.getName(),
                                    thisWarehouse.getPhone(),
                                    thisWarehouse.getCreateTime(),
                                    thisWarehouse.getUpdateTime(),
                                    thisWarehouse.getUpdateUser(),
                                    thisWarehouse.getIsLocked() == 1,
                                    thisWarehouse.getVideo()
                            )
            ));
        }

        return dtos;
    }

    @Override
    public List<ChannelShelfInventoryDto> GetListShelfAndInventory(GetShelfInventoryReq req)
    {
        if (ObjectUtil.isEmpty(req.getWarehouseId())){
            throw new JYZBAppException(JyzbV2ExceptionEnum.WAREHOUSEID_ERROR);
        }
        //获取货架信息
        List<Shelf> shelfs = shelfService.list(new LambdaQueryWrapper<Shelf>()
                .eq(Shelf::getType, "Smart")
                .isNotNull(Shelf::getUrl)
                .eq(Shelf::getWarehouseId, req.getWarehouseId())
                .eq(StrUtil.isNotBlank(req.getUrl()), Shelf::getUrl, req.getUrl()));

        if(CollectionUtil.isEmpty(shelfs)){
            return Collections.emptyList();
        }

        List<String> shelfIds = shelfs.stream().map(s -> s.getShelfId()).collect(Collectors.toList());

        //获取货架ID--物资映射
        Map<String, List<ChannelShelfInventoryVo>> invMap = channelMapper.GetShelfInventory(shelfIds)
                .stream()
                .collect(Collectors.groupingBy(s -> s.getShelfId()))
                .entrySet().stream()
                .collect(Collectors.toMap(s -> s.getKey(), s -> s.getValue()));

        List<ChannelShelfInventoryDto> dtos = new ArrayList<>();

        for(Shelf shelf : shelfs){
            List<ChannelShelfInventoryInfoDto> InfoList = new ArrayList<>();

            List<ChannelShelfInventoryVo> invs = invMap.getOrDefault(shelf.getShelfId(), new ArrayList<>());

            //分三层 ChannelShelfInventoryDto -> ChannelShelfInventoryInfoDto -> ChannelShelfInventoryDetailDto
            dtos.add(new ChannelShelfInventoryDto(
                    shelf.getShelfName(),
                    shelf.getUrl(),
                    shelf.getShelfName(),
                    invs.stream().collect(Collectors.groupingBy(s -> s.getTypeParentId()))
                            .entrySet().stream()
                            .map(s ->
                                    new ChannelShelfInventoryInfoDto(
                                            s.getValue().stream().findFirst().get().getTypeParentName(),
                                            s.getValue().stream()
                                                    .collect(Collectors.groupingBy(c -> c.getTypeId()))
                                                    .entrySet().stream()
                                                    .map(c ->
                                                            new ChannelShelfInventoryDetailDto(
                                                                    c.getValue().stream().findFirst().get().getTypeName(),
                                                                    (int)c.getValue().stream().count(),
                                                                    c.getValue().stream()
                                                                            .map(r -> r.getShelfLocation())
                                                                            .distinct()
                                                                            .collect(Collectors.joining(","))
                                                            ))
                                                    .collect(Collectors.toList())
                                    )
                            )
                            .collect(Collectors.toList())
            ));
        }

        return dtos;
    }

    @Override
    public List<ChannelEpcInfoReq> GetInvListByEpc(GetInvListByEpcReq req)
    {
        if(CollectionUtil.isEmpty(req.getEPCList()) || req.getEPCList().size() == 0){
            throw new JYZBAppException(JyzbV2ExceptionEnum.REQUEST_DATA_ERROR);
        }

        List<String> epcs = req.getEPCList().stream().map(s -> s.getEpc()).collect(Collectors.toList());

        List<Inventory> inventories = inventoryService.list(new LambdaQueryWrapper<Inventory>()
                .in(Inventory::getEpc, epcs));

        if(CollectionUtil.isEmpty(inventories)){
            return Collections.emptyList();
        }

        //获取仓库
        List<String> warehouseIds = inventories.stream()
                .filter(s -> s.getLocationType() == 0)
                .map(s -> s.getLocationId())
                .collect(Collectors.toList());
        Map<String, String> warehouseMap = warehouseIds == null || warehouseIds.size() < 1 ?
                new HashMap<>() :
                warehouseService.list(new LambdaQueryWrapper<Warehouse>().in(Warehouse::getId, warehouseIds))
                        .stream()
                        .collect(Collectors.toMap(s -> s.getId(), s -> s.getName()));

        //获取货架
        List<String> shelfIds = inventories.stream()
                .filter(s -> StrUtil.isNotBlank(s.getShelfId()))
                .map(s -> s.getShelfId()).collect(Collectors.toList());
        Map<String, Shelf> shelfMap = shelfIds == null || shelfIds.size() < 1 ?
                new HashMap<>() :
                shelfService.list(new LambdaQueryWrapper<Shelf>().in(Shelf::getShelfId, shelfIds))
                        .stream()
                        .collect(Collectors.toMap(s -> s.getShelfId(), s -> s));

        List<ChannelEpcInfoReq> dtos = new ArrayList<>();

        for (Inventory inventory : inventories){
            Shelf shelf = shelfMap.getOrDefault(inventory.getShelfId(), new Shelf());
            String warehouseName= warehouseMap.getOrDefault(inventory.getLocationId(), "");

            String[] shelfLocation = inventory.getShelfLocation() == null ?
                    new String[0] :
                    inventory.getShelfLocation().split("/");

            dtos.add(new ChannelEpcInfoReq(
                    inventory.getSupplierId(),
                    inventory.getId(),
                    shelfLocation.length > 1 ? Integer.parseInt(shelfLocation[1]) : null,
                    shelfLocation.length > 1 ? Integer.parseInt(shelfLocation[0]) : null,
                    shelfLocation.length > 1 ? Integer.parseInt(shelfLocation[2]) : null,
                    new ChannelShelfDto(
                            shelf.getShelfId(),
                            shelf.getCreateTime(),
                            shelf.getShelfName(),
                            shelf.getCode(),
                            shelf.getType(),
                            shelf.getWarehouseId(),
                            shelf.getSizeInfo(),
                            shelf.getShelfRanges(),
                            shelf.getShelfRows(),
                            shelf.getShelfColumns(),
                            shelf.getUrl(),
                            null
                    ),
                    shelf.getShelfName(),
                    shelf.getCode(),
                    inventory.getShelfId(),
                    inventory.getLostFlag() == 0 ? "normal" : "loss",
                    ConvertToV2CurrentState(inventory.getLocationType(), inventory.getBussinessState(), inventory.getLocationState()),
                    inventory.getTermState() == 1 ? 2 : 0,//2超期 0未超期
                    warehouseName,
                    inventory.getEpc(),
                    inventory.getSupplierName(),
                    inventory.getSizeName(),
                    inventory.getSizeId(),
                    inventory.getTypeName(),
                    inventory.getTypeId(),
                    inventory.getTypeName(),
                    inventory.getTypeId(),
                    inventory.getLocationId(),
                    ""
                    )
            );
        }

        return dtos;
    }

    @Override
    public List<ChannelShelfPositionDto> GetListEquipmentShelfPosition(GetListEquipmentShelfPositionReq req)
    {
        if (ObjectUtil.isEmpty(req.getWarehouseId())){
            throw new JYZBAppException(JyzbV2ExceptionEnum.WAREHOUSEID_ERROR);
        }
        if (ObjectUtil.isEmpty(req.getEquipmentDetailId())){
            throw new JYZBAppException(JyzbV2ExceptionEnum.EQUIPMENTDETAILID_ERROR);
        }
        //获取装备信息
        List<EquipmentShelfPositionVo> invs = channelMapper.GetEquipmentShelfPosition(req);

        if(CollectionUtil.isEmpty(invs)){
            return Collections.emptyList();
        }

        //装载返回Dto
        List<ChannelShelfPositionDto> dtos = new ArrayList<>();
        for(EquipmentShelfPositionVo inv : invs){
            //解析具体位置
            String[] postion = StrUtil.isBlank(inv.getShelfLocation()) ?
                    new String[0] :
                    inv.getShelfLocation().split("/");

            dtos.add(new ChannelShelfPositionDto(
                    inv.getShelfId(),
                    inv.getShelfName(),
                    postion.length > 1 ? Integer.parseInt(postion[2]) : null,
                    postion.length > 1 ? Integer.parseInt(postion[0]) : null,
                    postion.length > 1 ? Integer.parseInt(postion[1]) : null
                    ));
        }

        return dtos.stream().distinct().collect(Collectors.toList());
    }

    @Override
    public void UpdateFinger(UpdateFingerReq req)
    {
        if (ObjectUtil.isEmpty(req.getPoliceId())){
            throw new JYZBAppException(JyzbV2ExceptionEnum.POLICEID_ERROR);
        }
        if (CollectionUtil.isEmpty(req.getFingerList()) || req.getFingerList().size()<1){
            throw new JYZBAppException(JyzbV2ExceptionEnum.FINGERLIST_ERROR);
        }
        Policeman police = policemanService.getById(req.getPoliceId());

        if (police == null){
            throw new JYZBAppException(JyzbV2ExceptionEnum.POLICE_ERROR);
        }

        List<PoliceFinger> fingers = policeFingerService.list(
                new LambdaQueryWrapper<PoliceFinger>()
                        .eq(PoliceFinger::getPoliceId, req.getPoliceId())
                        .eq(PoliceFinger::getType, 0)
                        .isNotNull(PoliceFinger::getFingerNum)
        );
        if(CollectionUtil.isEmpty(fingers)){
            fingers = new ArrayList<>();
        }


        List<PoliceFinger> updateFingers = new ArrayList<>();
        List<PoliceFinger> addFingers = new ArrayList<>();
        for(FingerDetailReq finger : req.getFingerList()){
            Integer num = TryParseInt(finger.getFingerNum());

            Optional<PoliceFinger> thisFinger = fingers.stream().filter(s -> s.getFingerNum().equals(num)).findFirst();

            if(thisFinger.isPresent()){
                PoliceFinger f = thisFinger.get();
                f.setFingerInfo(finger.getFingerInfo());
                f.setUpdateTime(new Date());

                updateFingers.add(f);
            }else {
                addFingers.add(
                        new PoliceFinger(
                                null,
                                req.getPoliceId(),
                                "指纹" + num,
                                finger.getFingerInfo(),
                                num,
                                null,
                                new Date(),
                                new Date(),
                                0)
                );
            }
        }

        if(updateFingers.size() > 0){
            policeFingerService.updateBatchById(updateFingers);
        }
        if(addFingers.size() > 0){
            policeFingerService.saveBatch(addFingers);
        }
    }

    @Override
    public void BatchUpdateCardNo(BatchUpdateCardNoReq req)
    {
        if(CollectionUtil.isEmpty(req.getList())){
            return;
        }

        List<String> policeCodes = req.getList().stream().map(s -> s.getPoliceCode()).collect(Collectors.toList());

        List<Policeman> polices = policemanService.list(
                new LambdaQueryWrapper<Policeman>()
                        .in(Policeman::getPoliceCode,policeCodes)
        );

        if (polices == null){
            return;
        }

        List<Policeman> updateList =  new ArrayList<>();
        for(UpdateCardNoDetailReq detail : req.getList()){
            Optional<Policeman> police = polices.stream().filter(s -> s.getPoliceCode() == detail.getPoliceCode()).findFirst();

            if(!police.isPresent()){
                continue;
            }

            Policeman p = police.get();
            p.setDoorCode(detail.getCardNo());
            p.setUpdateTime(new Date());
            updateList.add(p);
        }

        if (updateList.size() > 0){
            policemanService.updateBatchById(updateList);
        }
    }

    @Override
    public List<ChannelBagDto> GetPrintBagList(GetPrintBagListReq req)
    {
        if (ObjectUtil.isEmpty(req.getOrgId())){
            throw new JYZBAppException(JyzbV2ExceptionEnum.ORGID_ERROR);
        }
        return channelMapper.GetPrintBagList(req);
    }

    @Override
    public Boolean UpdateBagState(UpdateBagStateReq req)
    {
        if (ObjectUtil.isEmpty(req.getId())){
            throw new JYZBAppException(JyzbV2ExceptionEnum.ID_ERROR);
        }
        Package bag = packageService.getById(req.getId());

        if(bag == null){
            throw new JYZBAppException(JyzbV2ExceptionEnum.EQUIPMENT_ERROR);
        }

        bag.setPrintState(1);
        bag.setUpdateTime(new Date());

        return packageService.updateById(bag);
    }

    @Override
    public List<ChannelEpcByBoxDto> GetEpcListByBoxMarkEpc(GetEpcListByBoxMarkEpcReq req)
    {

        if(CollectionUtil.isEmpty(req.getEpcList()) || req.getEpcList().size() < 1){
            throw new JYZBAppException(JyzbV2ExceptionEnum.REQUEST_DATA_ERROR);
        }

        List<String> epcList = req.getEpcList().stream().map(s -> s.getEpc()).collect(Collectors.toList());

        List<ChannelEpcByBoxDto> rs = channelMapper.GetEpcListByBoxMarkEpc(epcList);

        List<String> boxIds = rs.stream().map(s -> s.getId()).collect(Collectors.toList());
        Map<String, List<String>> boxEpcMap = inventoryService.list(new LambdaQueryWrapper<Inventory>().in(Inventory::getBoxMarkId, boxIds))
                .stream()
                .collect(Collectors.groupingBy(Inventory::getBoxMarkId))
                .entrySet()
                .stream()
                .collect(Collectors.toMap(
                        s -> s.getKey(),
                        s -> s.getValue()
                                .stream()
                                .map(v -> v.getEpc())
                                .collect(Collectors.toList())
                        )
                );

        if(MapUtil.isNotEmpty(boxEpcMap)){
            for (ChannelEpcByBoxDto dto : rs){
                List<String> thisEpcList = boxEpcMap.getOrDefault(dto.getId(), new ArrayList<>());
                dto.setEpcList(thisEpcList);
            }
        }
        return rs;
    }

    @Override
    public List<ChannelEpcByBoxInvDto> GetEpcListByBagInvEpc(GetEpcListByBagInvEpcReq req)
    {
        if(CollectionUtil.isEmpty(req.getEpcList())){
            return Collections.emptyList();
        }

        List<ChannelEpcByBoxInvDto> sqlRs = channelMapper.GetEpcListByBagInvEpc(req.getEpcList());

        //获取装备包下属EPC
        List<String> boxIds = sqlRs.stream().map(s -> s.getId()).collect(Collectors.toList());
        Map<String, List<String>> boxEpcMap = inventoryService.list(new LambdaQueryWrapper<Inventory>().in(Inventory::getBoxMarkId, boxIds))
                .stream()
                .collect(Collectors.groupingBy(Inventory::getBoxMarkId))
                .entrySet()
                .stream()
                .collect(Collectors.toMap(
                                s -> s.getKey(),
                                s -> s.getValue()
                                        .stream()
                                        .map(v -> v.getEpc())
                                        .collect(Collectors.toList())
                        )
                );

        List<ChannelEpcByBoxInvDto> rs = new ArrayList<>();

        if(MapUtil.isNotEmpty(boxEpcMap)){
            for (ChannelEpcByBoxInvDto dto : sqlRs){
                List<String> thisEpcList = boxEpcMap.getOrDefault(dto.getId(), new ArrayList<>());
                dto.setEpcList(thisEpcList);
            }
        }
        return rs;
    }

    @Override
    @Transactional
    public Boolean UploadFace(String id, MultipartFile picture)
    {
        try {
            if (StrUtil.isBlank(id)) {
                throw new JYZBAppException(JyzbV2ExceptionEnum.OPERATE_FAILED,":id为空");
            }

            if (picture == null) {
                throw new JYZBAppException(JyzbV2ExceptionEnum.OPERATE_FAILED,":文件为空");
            }

            if (picture.getSize() > 1024 * 1024 * 3) {
                throw new JYZBAppException(JyzbV2ExceptionEnum.OPERATE_FAILED,":文件过大");
            }

            Policeman police = policemanService.getById(id);
            if(police == null){
                throw new JYZBAppException(JyzbV2ExceptionEnum.POLICE_ERROR);
            }

            String fn = picture.getResource().getFilename();
            if (fn.contains(".jpg") || fn.contains(".png") || fn.contains(".bmp")) {
                SysFileInfoReq sysFileInfoReq = new SysFileInfoReq();
                sysFileInfoReq.setFileBucket("jyzb");
                sysFileInfoReq.setFileObjectName(UUID.randomUUID().toString());
                sysFileInfoReq.setFileLocation(3);
                SysFileInfoResp sysFileInfoResp = sysFileInfoService.uploadFile(picture, sysFileInfoReq);

                police.setUpdateTime(new Date());
                police.setPhoto(sysFileInfoResp.getFilePath());

                policemanService.updateById(police);
            }else {
                throw new JYZBAppException(JyzbV2ExceptionEnum.OPERATE_FAILED,":文件类型错误");
            }
        } catch (Exception ex) {
            throw new JYZBAppException(JyzbV2ExceptionEnum.OPERATE_FAILED,":文件上传失败");
        }
        return true;
    }

    @Override
    @Transactional
    public List<ChannelUploadRFIDDto> UploadRFIDNew(UploadRFIDReq req)
    {

        if (ObjectUtil.isEmpty(req.getOrgId())){
            throw new JYZBAppException(JyzbV2ExceptionEnum.ORGID_ERROR);
        }
        if (ObjectUtil.isEmpty(req.getWarehouseId())){
            throw new JYZBAppException(JyzbV2ExceptionEnum.WAREHOUSEID_ERROR);
        }
        if(CollectionUtil.isEmpty(req.getRFIDList()) && CollectionUtil.isEmpty(req.getBagRFIDList())){
            return Collections.emptyList();
        }

        //锁库判断
        Warehouse warehouse = warehouseService.getById(req.getWarehouseId());
        if(warehouse == null){
            throw new JYZBAppException(JyzbV2ExceptionEnum.WAREHOUSE_ERROR);
        }
        else if (warehouse.getIsLocked() == 1){
            throw new JYZBAppException(JyzbV2ExceptionEnum.WAREHOUSE_LOCK);
        }

        //获取组织机构信息
        PubOrg orgInfo = pubOrgService.getById(warehouse.getOrgIdInt());

        //获取操作人员
        Policeman police = StrUtil.isBlank(req.getPoliceId()) ?
                null :
                Optional.ofNullable(policemanService.getById(req.getPoliceId())).orElseGet(null) ;

        //待处理EPC
        List<String> invEpcs = req.getRFIDList().stream().map(s -> s.getRFID()).collect(Collectors.toList());
        //待处理EPC详细信息
//        List<Inventory> invs = inventoryService.list(
//            new LambdaQueryWrapper<Inventory>()
//                    .in(Inventory::getEpc, invEpcs)
//    );
        List<Inventory> invs = inventoryMapper.getInvNamesByEpcs(invEpcs);
        if(CollectionUtil.isEmpty(invs)){
            throw new JYZBAppException(JyzbV2ExceptionEnum.EQUIPMENT_ERROR);
        }

        //待处理EPC WarehouseInventory信息
        List<WarehouseInventory> warehouseInvs = Optional.ofNullable(
                warehouseInventoryService.list(
                        new LambdaQueryWrapper<WarehouseInventory>()
                                .in(WarehouseInventory::getEpc, invEpcs)
                )
        ).orElseGet(ArrayList::new);

        //库存统计信息
        List<InventorySummary> invSummarys = Optional.ofNullable(
                inventorySummaryService.list(
                        new LambdaQueryWrapper<InventorySummary>()
                                .eq(InventorySummary::getLocationId, req.getWarehouseId())
                                .in(CollectionUtil.isNotEmpty(invs), InventorySummary::getSizeId, invs.stream().map(i -> i.getSizeId()).distinct().collect(Collectors.toList()))
                )
        ).orElseGet(ArrayList::new);

        List<ChannelUploadRFIDDto> dtos = new ArrayList<>();

        //装备包拆解
        if(CollectionUtil.isNotEmpty(req.getBagRFIDList())){
            List<String> bagIds = req.getBagRFIDList().stream().map(s -> s.getRFID()).collect(Collectors.toList());
            List<Inventory> bagInvs = Optional.ofNullable(
                    inventoryService.list(
                            new LambdaQueryWrapper<Inventory>()
                                    .in(Inventory::getBoxMarkId, bagIds))
                    )
                    .orElseGet(ArrayList::new);

            invs.addAll(bagInvs);
            invEpcs.addAll(bagInvs.stream().map(s -> s.getEpc()).collect(Collectors.toList()));
        }

        //过滤报废装备
        List<Inventory> destoryInvs = invs.stream().filter(s -> StrUtil.isNotBlank(s.getState()) && (s.getState().equals("broken") || s.getState().equals("destory"))).collect(Collectors.toList());
        if(CollectionUtil.isNotEmpty(destoryInvs)){
            invEpcs.removeAll(destoryInvs.stream().map(s -> s.getEpc()).collect(Collectors.toList()));
        }

        //过滤装备包散件
        List<Inventory> bagSingleInvs = invs.stream().filter(s -> StrUtil.isNotBlank(s.getPackageId())).collect(Collectors.toList());
        if(CollectionUtil.isNotEmpty(bagSingleInvs)){
            invEpcs.removeAll(bagSingleInvs.stream().map(s -> s.getEpc()).collect(Collectors.toList()));
        }

        //查询开启的单据
        OrderMain order = orderMainService.getOne(
                new LambdaQueryWrapper<OrderMain>()
                        .eq(OrderMain::getOrderType, req.getCurrentState() == 0 ? "out" : "in")
                        .eq(OrderMain::getIsOpen, 1)
                        .eq(req.getCurrentState() == 0 , OrderMain::getStartOrgId, req.getOrgId())
                        .eq(req.getCurrentState() == 1 , OrderMain::getEndOrgId, req.getOrgId())
        );

        List<OrderDetail> orderDetails = order == null ?
                null :
                orderDetailService.list(
                        new LambdaQueryWrapper<OrderDetail>()
                                .eq(OrderDetail::getOrderId, order.getId())
        );

        List<String> normalEpcs = new ArrayList<>();//没有匹配单据的装备  --日常出入库处理
        List<String> orderEpcs = new ArrayList<>();//存在匹配单据的装备

        //匹配单据
        if(order != null && CollectionUtil.isNotEmpty(orderDetails)){
            //采购 赠与
            if(order.getBussinessType().equals("purchase") || order.getBussinessType().equals("gift")){
                normalEpcs = invs.stream().map(s -> s.getEpc()).collect(Collectors.toList());
                List<String> finalNormalEpcs = normalEpcs;
                orderEpcs = Optional.ofNullable(invEpcs.stream().filter(s -> ! finalNormalEpcs.contains(s)).collect(Collectors.toList())).orElseGet(ArrayList::new);
;
                //查询打印单据
                List<PrintEpcs> printOrders = printEpcsService.list(
                        new LambdaQueryWrapper<PrintEpcs>()
                                .in(PrintEpcs::getOrderDetailId, orderDetails.stream().map(s -> s.getId()).collect(Collectors.toList()))
                                .in(PrintEpcs::getEpc, invEpcs)
                );

                if(printOrders != null){
                    //更新单据
                    List<Inventory> purchaseInvs = new ArrayList<>();
                    List<WarehouseInventory> purchaseWarehouseInvs = new ArrayList<>();
                    Set<Map.Entry<String, List<PrintEpcs>>> groupPrintOrders = printOrders.stream().collect(Collectors.groupingBy(s -> s.getOrderDetailId())).entrySet();

                    for (Map.Entry<String, List<PrintEpcs>> entry : groupPrintOrders){
                        OrderDetail thisDetail = orderDetails.stream().filter(s -> s.getId().equals(entry.getKey())).findFirst().get();

                        //获取并更新DetailJson
                        List<DetailJsonReq> baseDetailJson = JSON.parseArray(thisDetail.getDetailJson(), DetailJsonReq.class);

                        Map<BigDecimal, DetailJsonReq> detailJsonMap = Optional
                                .ofNullable(baseDetailJson)
                                .orElseGet(ArrayList :: new)
                                .stream()
                                .collect(Collectors.toMap(s -> s.getPrice(), s -> s));

                        for (PrintEpcs printEpc : entry.getValue()){
                            BigDecimal key = printEpc.getPrice();

                            DetailJsonReq value = detailJsonMap.getOrDefault(key, null);
                            if (value == null){
                                detailJsonMap.put(key,
                                        new DetailJsonReq(
                                                warehouse.getId(),
                                                warehouse.getName(),
                                                thisDetail.getTypeId(),
                                                thisDetail.getTypeName(),
                                                thisDetail.getSizeId(),
                                                thisDetail.getSizeName(),
                                                printEpc.getPrice(),
                                                0,
                                                1
                                        )
                                );
                            }
                            else{
                                value.setNum(value.getNum() + 1);
                            }

                            //新增装备
                            Inventory inv = new Inventory();
                            inv.setEpc(printEpc.getEpc());
                            inv.setTypeId(thisDetail.getTypeId());
                            inv.setSizeId(thisDetail.getSizeId());
                            inv.setEpcType(0);
                            inv.setMaintenancePeriod(printEpc.getRepairCycle());
                            inv.setWarrantyPeriod(printEpc.getWarrantyCycle());
                            inv.setProperty(0);
                            inv.setLocationId(warehouse.getId());
                            inv.setSupplierId(printEpc.getSupplierId());
                            inv.setPrice(printEpc.getPrice());
                            inv.setId(UUID.randomUUID().toString());
                            inv.setCreateTime(new Date());
                            inv.setUpdateTime(new Date());
                            inv.setState("normal");
                            inv.setBussinessState("normal");
                            inv.setLocationState("in");
                            inv.setLocationType(0);
                            purchaseInvs.add(inv);

                            WarehouseInventory winv = new WarehouseInventory();
                            winv.setLocationState("in");
                            winv.setLocationType("0");
                            winv.setOrgId(warehouse.getOrgIdInt());
                            winv.setFlag(0);
                            winv.setEpcType(0);
                            winv.setCreateTime(new Date());
                            winv.setUpdateTime(new Date());
                            purchaseWarehouseInvs.add(winv);

                            dtos.add(new ChannelUploadRFIDDto(
                                    printEpc.getEpc(),
                                    req.getCurrentState().equals(0) ? 1 : 0,
                                    0,
                                    thisDetail.getTypeName(),
                                    thisDetail.getSizeName(),
                                    "single",
                                    ""
                            ));
                        }

                        List<DetailJsonReq> detailJsonList = Optional
                                .ofNullable(detailJsonMap.values().stream().collect(Collectors.toList()))
                                .orElseGet(ArrayList :: new);
                        String detailJson = JSON.toJSONString(detailJsonList);

                        //更新子单
                        thisDetail.setUpdateTime(new Date());
                        thisDetail.setActualTotalPrice(CollectionUtil.isNotEmpty(detailJsonList) ?
                                detailJsonList.stream()
                                        .map(s -> new BigDecimal(s.getNum().toString()).multiply(s.getPrice()))
                                        .reduce(BigDecimal.ZERO, BigDecimal :: add) :
                                thisDetail.getActualTotalPrice().add(entry.getValue().stream().map(s -> s.getPrice()).reduce(BigDecimal.ZERO, BigDecimal :: add))
                        );
                        thisDetail.setActualNum(CollectionUtil.isNotEmpty(detailJsonList) ? detailJsonList.stream().mapToInt(s -> s.getNum()).sum() : entry.getValue().size());
                        thisDetail.setDetailJson(detailJson);

                        //采购入库新增装备添加Redis
                        if(order.getBussinessType() == "purchase"){
                            outInRecordRedisCache.addInvRecord(order.getId(), purchaseInvs, DateTimeUtil.TimeDateToLong(new Date()));
                            outInRecordRedisCache.addInvWareRecord(order.getId(), purchaseWarehouseInvs, DateTimeUtil.TimeDateToLong(new Date()));
                        }
                    }
                }
            }else {
                //快捷建单处理
                List<OrderDetail> quickDetails = orderDetails.stream().filter(s -> StrUtil.isBlank(s.getSizeId())).collect(Collectors.toList());

                if(CollectionUtil.isNotEmpty(quickDetails)){
                    List<String> quickTypes = quickDetails
                            .stream()
                            .map(s -> s.getTypeId())
                            .distinct()
                            .collect(Collectors.toList());

                    List<String[]> quickSizes = invs
                            .stream()
                            .map(s -> new String[] { s.getSizeId(), s.getSizeName() })
                            .collect(Collectors.toList());

                    for(String[] sizeInfo : quickSizes){
                        Optional<OrderDetail> thisDetailInfo = quickDetails.stream().filter(s -> s.getSizeId() == null).findFirst();
                        if(thisDetailInfo.isPresent()){
                            OrderDetail thisDetail = thisDetailInfo.get();

                            thisDetail.setSizeId(sizeInfo[0]);
                            thisDetail.setSizeName(sizeInfo[1]);
                        }
                        else {
                            OrderDetail newDetail = new OrderDetail();
                            BeanUtil.copyProperties(orderDetails.get(0), newDetail);
                            newDetail.setSizeId(sizeInfo[0]);
                            newDetail.setSizeName(sizeInfo[1]);

                            quickDetails.add(newDetail);
                            orderDetails.add(newDetail);
                        }
                    }

                    if(!orderDetailService.saveOrUpdateBatch(orderDetails)){
                        throw new JYZBAppException(JyzbV2ExceptionEnum.OPERATE_FAILED, ":匹配快捷单据失败");
                    }
                }

                for(OrderDetail thisDetail : orderDetails){
                    //获取并更新DetailJson
                    List<DetailJsonReq> baseDetailJson = JSON.parseArray(thisDetail.getDetailJson(), DetailJsonReq.class);

                    Map<BigDecimal, DetailJsonReq> detailJsonMap = Optional
                            .ofNullable(baseDetailJson)
                            .orElseGet(ArrayList :: new)
                            .stream()
                            .collect(Collectors.toMap(s -> s.getPrice(), s -> s));

                    List<Inventory> mapInvs = invs
                            .stream()
                            .filter(s -> s.getTypeId().equals(thisDetail.getTypeId()) && s.getSizeId().equals(thisDetail.getSizeId()))
                            .collect(Collectors.toList());

                    if(CollectionUtil.isEmpty(mapInvs)){
                        continue;
                    }

                    orderEpcs.addAll(mapInvs.stream().map(s -> s.getEpc()).collect(Collectors.toList()));

                    for (Inventory mapInv : mapInvs){
                        DetailJsonReq mapValue =  detailJsonMap.getOrDefault(mapInv.getPrice(), null);
                        if(mapValue == null){
                            detailJsonMap.put(mapInv.getPrice(),
                                    new DetailJsonReq(
                                            warehouse.getId(),
                                            warehouse.getName(),
                                            thisDetail.getTypeId(),
                                            thisDetail.getTypeName(),
                                            thisDetail.getSizeId(),
                                            thisDetail.getSizeName(),
                                            mapInv.getPrice(),
                                            0,
                                            1
                                    )
                            );
                        }else{
                            mapValue.setNum(mapValue.getNum() + 1);
                        }
                    }

                    List<DetailJsonReq> detailJsonList = Optional
                            .ofNullable(detailJsonMap.values().stream().collect(Collectors.toList()))
                            .orElseGet(ArrayList :: new);
                    String detailJson = JSON.toJSONString(detailJsonList);

                    //更新子单
                    thisDetail.setUpdateTime(new Date());
                    thisDetail.setActualTotalPrice(StrUtil.isNotBlank(detailJson) ?
                            detailJsonList.stream()
                                    .map(s -> new BigDecimal(s.getNum().toString()).multiply(s.getPrice()))
                                    .reduce(BigDecimal.ZERO, BigDecimal :: add) :
                            thisDetail.getActualTotalPrice().add(mapInvs.stream().map(s -> s.getPrice()).reduce(BigDecimal.ZERO, BigDecimal :: add))
                    );
                    thisDetail.setActualNum(CollectionUtil.isNotEmpty(detailJsonList) ?
                            detailJsonList.stream().mapToInt(s -> s.getNum()).sum() :
                            mapInvs.size()
                    );
                    thisDetail.setModifyQuantity(CollectionUtil.isNotEmpty(detailJsonList) ?
                            detailJsonList.stream().mapToInt(s -> s.getNum()).sum() :
                            mapInvs.size()
                    );
                    thisDetail.setDetailJson(detailJson);
                }

                List<String> finalOrderEpcs = orderEpcs;
                normalEpcs = invEpcs.stream().filter(s -> !finalOrderEpcs.contains(s)).collect(Collectors.toList());
            }

            //更新主单
            order.setOrderState("finished");
            order.setUpdateTime(new Date());
            order.setActualQuantity(orderDetails.stream().mapToInt(s -> s.getActualNum()).sum());
            order.setPrice(orderDetails.stream().map(s -> Optional.ofNullable(s.getActualTotalPrice()).orElse(BigDecimal.ZERO)).reduce(BigDecimal.ZERO, BigDecimal :: add));
            order.setIsOpen(1);
            //数据库应用更改
            orderMainService.updateById(order);
            orderDetailService.updateBatchById(orderDetails);
        }
        else {
            normalEpcs.addAll(invEpcs);
        }

        //添加出入库记录
        //日常出入库
        if(CollectionUtil.isNotEmpty(normalEpcs)){
            LogSummary normalLogSummary = new LogSummary();
            List<LogDetail> normalLogDetails = new ArrayList<>();

            List<String> finalNormalEpcs1 = normalEpcs;

            List<Inventory> sss = invs
                    .stream()
                    .filter(s -> finalNormalEpcs1.contains(s.getEpc()))
                    .collect(Collectors.toList());

            List<Inventory> normalInvs = Optional
                    .ofNullable(invs
                            .stream()
                            .filter(s -> finalNormalEpcs1.contains(s.getEpc()))
                            .collect(Collectors.toList()))
                    .orElseGet(ArrayList :: new);

            //生成主记录
            normalLogSummary.setOrgId(orgInfo.getOrgId());
            normalLogSummary.setOrgName(orgInfo.getOrgName());
            normalLogSummary.setDeviceType(2);//通道
            normalLogSummary.setLocationId(warehouse.getId());
            normalLogSummary.setLocationName(warehouse.getName());
            normalLogSummary.setLocationType(0);//仓库
            normalLogSummary.setUseTime(new Date());
            normalLogSummary.setBussinessType("normal");
            normalLogSummary.setUserName(police == null ? "" : police.getName());
            normalLogSummary.setPicture(req.getPicUrl());

            List<EquipmentType> normalTypes = Optional.ofNullable(
                    equipmentTypeService.list(
                            new LambdaQueryWrapper<EquipmentType>()
                                    .in(EquipmentType::getId, normalInvs.stream().map(s -> s.getTypeId()).collect(Collectors.toList()))
                    )
            ).orElse(new ArrayList<>());

            normalLogSummary.setEquipmentList(normalTypes.stream().map(s -> s.getName()).distinct().collect(Collectors.joining(",")));
            normalLogSummary.setOutInState(req.getCurrentState() == 0 ? "out" : "in");
            normalLogSummary.setNumber(normalInvs.size());
            normalLogSummary.setPrice(normalInvs.stream().map(s -> s.getPrice()).reduce(BigDecimal.ZERO, BigDecimal :: add));
            normalLogSummary.setCreateTime(new Date());
            normalLogSummary.setUpdateTime(new Date());

            if(!logSummaryService.save(normalLogSummary)){
                throw new JYZBAppException(JyzbV2ExceptionEnum.OPERATE_FAILED, ":记录失败");
            }

            //生成子记录
            for (Inventory normalInv : normalInvs){
                LogDetail logDetail = new LogDetail();
                logDetail.setSummaryId(normalLogSummary.getId());
                logDetail.setEpc(normalInv.getEpc());
                logDetail.setBussinessType("normal");
                logDetail.setInventoryId(normalInv.getId());
                logDetail.setTypeId(normalInv.getTypeId());
                logDetail.setTypeName(normalInv.getTypeName());
                logDetail.setSizeId(normalInv.getSizeId());
                logDetail.setSizeName(normalInv.getSizeName());
                logDetail.setSupplierId(normalInv.getSupplierId());
                logDetail.setSupplierName(normalInv.getSupplierName());
                logDetail.setErrorState(0);
                logDetail.setOutInState(normalLogSummary.getOutInState());
                logDetail.setCreateTime(normalLogSummary.getCreateTime());
                logDetail.setUpdateTime(normalLogSummary.getUpdateTime());
                logDetail.setPrice(normalInv.getPrice());
                logDetail.setProperty(0);

                normalLogDetails.add(logDetail);

                //更新库存统计
                if(!normalInv.getLocationState().equals(req.getCurrentState() == 0 ? "out" : "in"))
                {
                    invSummarys.stream()
                            .filter(s -> s.getSizeId().equals(normalInv.getSizeId()))
                            .forEach(s ->
                            {
                                if(normalLogSummary.getOutInState().equals("in")){
                                    s.setStockNumber(s.getStockNumber() + 1);
                                    s.setOutboundNumber(s.getOutboundNumber() - 1);
                                }else{
                                    s.setStockNumber(s.getStockNumber() - 1);
                                    s.setOutboundNumber(s.getOutboundNumber() + 1);
                                }
                            });
                }

                //更新装备状态
                normalInv.setBussinessState("normal");
                normalInv.setState("normal");
                normalInv.setLocationState(normalLogSummary.getOutInState());

                dtos.add(new ChannelUploadRFIDDto(
                        normalInv.getEpc(),
                        req.getCurrentState().equals(0) ? 1 : 0,
                        normalInv.getTermState() != null && normalInv.getTermState().equals(1) ? 2 : 0,
                        normalInv.getTypeName(),
                        normalInv.getSizeName(),
                        "single",
                        ""
                ));
            }

            if(!logDetailService.saveBatch(normalLogDetails)){
                throw new JYZBAppException(JyzbV2ExceptionEnum.OPERATE_FAILED, ":记录失败");
            }

            if(!inventoryService.updateBatchById(normalInvs)){
                throw new JYZBAppException(JyzbV2ExceptionEnum.OPERATE_FAILED, ":记录失败");
            }

            List<Inventory> test = inventoryService.list(new LambdaQueryWrapper<Inventory>()
                    .in(Inventory::getEpc, normalInvs.stream().map(s -> s.getEpc()).collect(Collectors.toList())));

            //更新库存状态
            warehouseInvs.stream().filter(s -> finalNormalEpcs1.contains(s.getEpc())).forEach(s -> s.setLocationState(normalLogSummary.getOutInState()));
        }
        //单据出入库
        if(CollectionUtil.isNotEmpty(orderEpcs)){
            LogSummary orderLogSummary = new LogSummary();
            List<LogDetail> orderLogDetails = new ArrayList<>();

            List<String> finalOrderEpcs = orderEpcs;
            List<Inventory> orderInvs = Optional
                    .ofNullable(invs
                            .stream()
                            .filter(s -> finalOrderEpcs.contains(s.getEpc()))
                            .collect(Collectors.toList()))
                    .orElseGet(ArrayList :: new);

            //生成主记录
            orderLogSummary.setOrderMainId(order.getId());
            orderLogSummary.setOrderCode(order.getOrderCode());
            orderLogSummary.setBussinessType(order.getBussinessType());

            orderLogSummary.setOrgId(orgInfo.getOrgId());
            orderLogSummary.setOrgName(orgInfo.getOrgName());
            orderLogSummary.setDeviceType(2);//通道
            orderLogSummary.setLocationId(warehouse.getId());
            orderLogSummary.setLocationName(warehouse.getName());
            orderLogSummary.setLocationType(0);//仓库
            orderLogSummary.setUseTime(new Date());
            orderLogSummary.setUserName(police == null ? "" : police.getName());
            orderLogSummary.setPicture(req.getPicUrl());

            List<EquipmentType> orderTypes = Optional.ofNullable(
                    equipmentTypeService.list(
                            new LambdaQueryWrapper<EquipmentType>()
                                    .in(EquipmentType::getId, orderInvs.stream().map(s -> s.getTypeId()).collect(Collectors.toList()))
                    )
            ).orElse(new ArrayList<>());
            orderLogSummary.setEquipmentList(orderTypes.stream().map(s -> s.getName()).distinct().collect(Collectors.joining(",")));

            orderLogSummary.setOutInState(req.getCurrentState() == 0 ? "out" : "in");
            orderLogSummary.setNumber(orderInvs.size());
            orderLogSummary.setPrice(orderInvs.stream().map(s -> Optional.ofNullable(s.getPrice()).orElse(BigDecimal.ZERO)).reduce(BigDecimal.ZERO, BigDecimal :: add));
            orderLogSummary.setCreateTime(new Date());
            orderLogSummary.setUpdateTime(new Date());

            if(!logSummaryService.save(orderLogSummary)){
                throw new JYZBAppException(JyzbV2ExceptionEnum.OPERATE_FAILED, ":记录失败");
            }

            //生成子记录
            for (Inventory orderlInv : orderInvs){
                LogDetail logDetail = new LogDetail();
                logDetail.setBussinessType(order.getBussinessType());
                logDetail.setSummaryId(orderLogSummary.getId());
                logDetail.setEpc(orderlInv.getEpc());
                logDetail.setBussinessType(order.getBussinessType());
                logDetail.setInventoryId(orderlInv.getId());
                logDetail.setTypeId(orderlInv.getTypeId());
                logDetail.setTypeName(orderlInv.getTypeName());
                logDetail.setSizeId(orderlInv.getSizeId());
                logDetail.setSizeName(orderlInv.getSizeName());
                logDetail.setSupplierId(orderlInv.getSupplierId());
                logDetail.setSupplierName(orderlInv.getSupplierName());
                logDetail.setErrorState(0);
                logDetail.setOutInState(orderLogSummary.getOutInState());
                logDetail.setCreateTime(orderLogSummary.getCreateTime());
                logDetail.setUpdateTime(orderLogSummary.getUpdateTime());
                logDetail.setPrice(orderlInv.getPrice());
                logDetail.setProperty(0);

                orderLogDetails.add(logDetail);

                //更新装备状态
                orderlInv.setBussinessState(order.getBussinessType());
                orderlInv.setState(order.getBussinessType().equals("borken") ?
                        "borken" :
                        order.getBussinessType().equals("destruction") ?
                        "destory" :
                        (order.getBussinessType().equals("repair") && order.getOrderType().equals("out")) ?
                        "fix" :
                        "normal"
                );
                orderlInv.setLocationState(orderLogSummary.getOutInState());

                dtos.add(new ChannelUploadRFIDDto(
                        orderlInv.getEpc(),
                        req.getCurrentState().equals(0) ? 1 : 0,
                        orderlInv.getTermState() != null && orderlInv.getTermState().equals(1) ? 2 : 0,
                        orderlInv.getTypeName(),
                        orderlInv.getSizeName(),
                        "single",
                        ""
                ));

                //更新库存统计
//                invSummarys.stream()
//                        .filter(s -> s.getSizeId().equals(orderlInv.getSizeId()))
//                        .forEach(s ->
//                        {
//                            switch (order.getBussinessType()){
//                                case "destruction":
//                                    s.setDestructionNumber(s.getDestructionNumber() + 1);
//                                    s.setDestructionPrice(s.getDestructionPrice().add(orderlInv.getPrice()));
//
//                                    s.setStockNumber(s.getStockNumber() - 1);
//
//                                    break;
//                                case "repair":
//                                    if(orderLogSummary.getOutInState().equals("in")){
//                                        s.setFixCount(s.getFixCount() + 1);
//
//                                        s.setFixNumber(s.getFixNumber() - 1);
//                                    }else{
//                                        s.setFixNumber(s.getFixNumber() + 1);
//                                    }
//                                    break;
//                                case "use":
//                                    s.setUseCount(s.getUseCount() + 1);
//                                    s.setUseNumber(s.getUseNumber() + 1);
//
//                                    s.setStockNumber(s.getStockNumber() - 1);
//                                    s.setOutboundNumber(s.getOutboundNumber() + 1);
//                                    break;
//                                case "return":
//                                    s.setUseNumber(s.getUseNumber() - 1);
//
//                                    s.setStockNumber(s.getStockNumber() + 1);
//                                    s.setOutboundNumber(s.getOutboundNumber() - 1);
//                                    break;
//                                default:
//                                    if(orderLogSummary.getOutInState().equals("in")){
//                                        s.setStockNumber(s.getStockNumber() + 1);
//                                        s.setOutboundNumber(s.getOutboundNumber() - 1);
//                                    }else{
//                                        s.setStockNumber(s.getStockNumber() - 1);
//                                        s.setOutboundNumber(s.getOutboundNumber() -+1);
//                                    }
//                                    break;
//                            }
//                        });
            }

            if(!logDetailService.saveBatch(orderLogDetails)){
                throw new JYZBAppException(JyzbV2ExceptionEnum.OPERATE_FAILED, ":记录失败");
            }

            if(!inventoryService.updateBatchById(orderInvs)){
                throw new JYZBAppException(JyzbV2ExceptionEnum.OPERATE_FAILED, ":记录失败");
            }

            //更新库存状态
            warehouseInvs.stream().filter(s -> finalOrderEpcs.contains(s.getEpc())).forEach(s -> s.setLocationState(orderLogSummary.getOutInState()));
        }

        inventorySummaryService.updateBatchById(invSummarys);
        warehouseInventoryService.updateBatchById(warehouseInvs);

        return dtos;
    }

    @Override
    public ChannelOpenOrderDto GetOpenOrderInfo(GetOpenOrderInfoReq req)
    {

        if (ObjectUtil.isEmpty(req.getWarehouseId())){
            throw new JYZBAppException(JyzbV2ExceptionEnum.WAREHOUSE_ERROR);
        }
        //单据类型转换
        if(StrUtil.isNotBlank(req.getOrderType())){
            switch (req.getOrderType()){
                case "借用":
                    req.setOrderType("use");
                    break;
                case "领用":
                    req.setOrderType("use");
                    break;
                case "销毁":
                    req.setOrderType("destruction");
                    break;
                case "跨库借用":
                    req.setOrderType("use");
                    break;
                case "跨库归还":
                    throw new JYZBAppException(JyzbV2ExceptionEnum.OPERATE_FAILED,":异常单据类型");
                    //req.setOrderType("return");
                    //break;
                case "库存调拨":
                    req.setOrderType("allocate");
                    break;
                default:
                    throw new JYZBAppException(JyzbV2ExceptionEnum.OPERATE_FAILED,":异常单据类型");
            }
        }

        //查询仓库所在组织机构
        Warehouse warehouse = warehouseService.getById(req.getWarehouseId());
        if(warehouse == null){
            throw new JYZBAppException(JyzbV2ExceptionEnum.WAREHOUSE_ERROR);
        }

        //获取单据
        OrderMain order = orderMainService.getOne(
                new LambdaQueryWrapper<OrderMain>()
                        .eq(OrderMain::getIsOpen, 1)
                        .ne(OrderMain::getManualState, 1)
                        .eq(StrUtil.isNotBlank(req.getOrderType()), OrderMain::getOrderType, req.getOrderType())
                        .and(v -> v.and(s -> s
                                        .eq(OrderMain::getOrderType, "in")
                                        .eq(OrderMain::getEndOrgId, warehouse.getOrgIdInt())
                                        )
                                .or(s -> s
                                        .eq(OrderMain::getOrderType, "out")
                                        .eq(OrderMain::getStartOrgId, warehouse.getOrgIdInt()
                                        )
                                )
                        )
        );

        if(order == null){
            return new ChannelOpenOrderDto();
        }

        List<OrderDetail> orderDetails = orderDetailService.list(
                new LambdaQueryWrapper<OrderDetail>().eq(OrderDetail::getOrderId, order.getId())
        );

        //Dto装载
        ChannelOpenOrderDto dto = new ChannelOpenOrderDto();
        if(req.getOrderType() == "destruction" || req.getOrderType() == "use"){
            dto.setId(order.getId());
            dto.setOrderCode(order.getOrderCode());
            dto.setWarehouseId("DefaultWarehouse");
            dto.setWarehouseName("仓库");
            dto.setType(req.getOrderType() == "destruction" ? 20 : 3);//2借用，3领用 20销毁
            dto.setCreateTime(new Date());
            dto.setNote(order.getNote());
            dto.setPoliceNote(order.getNote());
            dto.setApplyName(order.getCreateUser());
            dto.setChangeFlag(0);
            dto.setActionType(req.getOrderType() == "destruction" ? 2 : 1);//0借用 1领用 2报废
            dto.setDetailList(orderDetails.stream()
                    .map(s -> new ChannelOpenOrderDetailDto(
                            s.getId().toString(),
                            s.getSizeId(),
                            s.getSizeName(),
                            s.getTypeId(),
                            s.getTypeName(),
                            s.getPlanNum(),
                            s.getSupplierId(),
                            s.getSupplierName(),
                            s.getTypeId(),
                            s.getTypeName(),
                            s.getPlanNum()
                            )
                    ).collect(Collectors.toList())
            );
            dto.setApplyResult(new ChannelOpenOrderApplyDto(
                    0,//0未出去 1已出去 2已回来
                    orderDetails.stream()
                            .map(s -> new ChannelOpenOrderApplyResultDto(
                                    s.getId().toString(),
                                    s.getPlanNum(),
                                    s.getTypeId(),
                                    s.getTypeName(),
                                    s.getTypeId(),
                                    s.getSizeId(),
                                    s.getSizeName(),
                                    s.getSupplierId(),
                                    s.getSupplierName(),
                                    s.getActualNum(),
                                    s.getActualNum(),
                                    s.getActualNum() >= s.getPlanNum() ? 1 : 0 //0未出去 1已出去 2已回来
                            ))
                            .collect(Collectors.toList())
                    )
            );
        }
        else if(req.getOrderType() == "allocate" || req.getOrderType() == "return")
        {
            dto.setType(req.getOrderType() == "allocate" ? 9 : 7);
            dto.setOrgId(warehouse.getOrgIdInt().toString());
            dto.setUpdateTime(order.getUpdateTime());
            dto.setCurrentStepName("调拨申请");
            dto.setCurrentOrg(warehouse.getOrgIdInt().toString());
            dto.setId(order.getId());
            dto.setApplyName(order.getCreateUser());
            dto.setApplyTime(order.getCreateTime());
            dto.setNote(order.getNote());
            dto.setCreateTime(order.getCreateTime());
            dto.setWarehouseId("DefaultWarehouse");
            dto.setWarehouseName("仓库");
            dto.setOrder(order.getOrderCode());
            dto.setTransferId(order.getId());
            dto.setTargetId(order.getEndOrgId().toString());
            dto.setTargetName(order.getEndOrgName());
            dto.setDetailList(orderDetails.stream()
                    .map(s -> new ChannelOpenOrderDetailDto(
                            s.getId().toString(),
                            s.getSizeId(),
                            s.getSizeName(),
                            s.getTypeId(),
                            s.getTypeName(),
                            s.getPlanNum(),
                            s.getSupplierId(),
                            s.getSupplierName(),
                            s.getTypeId(),
                            s.getTypeName(),
                            s.getPlanNum()
                            ))
                    .collect(Collectors.toList())
            );
            dto.setRealityDetailList(orderDetails.stream()
                    .map(s -> new ChannelOpenOrderRealityDto(
                            s.getId().toString(),
                            s.getSizeId(),
                            s.getSizeName(),
                            s.getTypeId(),
                            s.getTypeId(),
                            "DefaultWarehouse",
                            "仓库",
                            s.getTypeName(),
                            s.getPlanNum(),
                            s.getActualNum(),
                            s.getActualNum(),
                            s.getActualNum() < s.getPlanNum() ? 0 : order.getOrderType() == "in" ? 2 : 1, //0未出去 1已出去 2已回来
                            s.getSupplierId(),
                            s.getSupplierName()
                    ))
                    .collect(Collectors.toList()));
        }

        return dto;
    }

    private Integer TryParseInt(String integer)
    {
        try{
            return Integer.parseInt(integer);
        }catch (NumberFormatException e){
            return 0;
        }
    }

    /**
     * 3.0装备状态转2.0
     * @param locationType 装备位置
     * @param bussinessState 业务状态
     * @param locationState 在库状态
     * @return
     */
    private Integer ConvertToV2CurrentState(Integer locationType, String bussinessState, String locationState){
        /*
        0:库存内
        1:调拨中
        2:借出中
        3:单警柜中
        4:维修中
        6:已报废
        7:单警柜出库中
        8:领用中
        9:异常出库
        10异常入库
        11不属于本仓库的物资
        14本仓库借用中
        15跨仓库借用中
        17跨仓库归还中
        */

        Integer rs = 0;

        if(locationType == 1){
            rs = locationState == "out" ? 3 : 7;
        }else {
            if(locationState == "in"){
                switch (bussinessState){
                    case "normal"://无业务
                        rs = 0;
                        break;
                    case "transfer"://调拨
                        rs = 1;
                        break;
                    case "remove"://报废
                        rs = 6;
                        break;
                    case "destruction"://销毁
                        rs = 6;
                        break;
                    default:
                        rs = 0;
                        break;
                }
            }else {
                switch (bussinessState){
                    case "normal"://无业务
                        rs = 2;
                        break;
                    case "transfer"://调拨
                        rs = 1;
                        break;
                    case "borrow"://借用
                        rs = 2;
                        break;
                    case "take"://领用
                        rs = 8;
                        break;
                    case "remove"://报废
                        rs = 6;
                        break;
                    case "destruction"://销毁
                        rs = 6;
                        break;
                    case "repair"://维修
                        rs = 4;
                        break;
                    default:
                        rs = 2;
                        break;
                }
            }
        }

        return rs;
    }
}