/*
 *  Copyright 2019-2020 Zheng Jie
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.youchain.businessdata.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.youchain.basicdata.domain.Item;
import com.youchain.basicdata.domain.Point;
import com.youchain.basicdata.domain.Stock;
import com.youchain.basicdata.repository.ItemRepository;
import com.youchain.basicdata.repository.PointRepository;
import com.youchain.basicdata.repository.StockRepository;
import com.youchain.basicdata.repository.StockTypeRepository;
import com.youchain.businessdata.ReturnJson.RPTaskList;
import com.youchain.businessdata.domain.*;
import com.youchain.businessdata.inputJson.IPTask;
import com.youchain.businessdata.repository.*;
import com.youchain.businessdata.service.*;
import com.youchain.exception.handler.ApiResult;
import com.youchain.modules.system.domain.Dept;
import com.youchain.utils.*;
import lombok.RequiredArgsConstructor;
import com.youchain.businessdata.service.dto.TaskDto;
import com.youchain.businessdata.service.dto.TaskQueryCriteria;
import com.youchain.businessdata.service.mapstruct.TaskMapper;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.SQLQuery;
import org.hibernate.transform.AliasToEntityMapResultTransformer;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.*;
import java.io.IOException;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.servlet.http.HttpServletResponse;

/**
 * @author houjianlan
 * @website https://eladmin.vip
 * @description 服务实现
 * @date 2023-08-16
 **/
@Service
@RequiredArgsConstructor
@Slf4j
@Transactional
public class TaskServiceImpl implements TaskService {

    private final TaskRepository taskRepository;
    private final TaskMapper taskMapper;
    private final AsnRepository asnRepository;
    private final InventoryRepository inventoryRepository;
    private final InventoryService inventoryService;
    private final AgvTaskService agvTaskService;
    private final PickDetailRepository pickDetailRepository;
    private final AsnDetailRepository asnDetailRepository;
    private final StockTypeRepository stockTypeRepository;
    private final AsnDetailService asnDetailService;
    private final InventoryLogService inventoryLogService;
    private final EntityManager entityMapper;
    private  final StockRepository stockRepository;
    private  final PointRepository pointRepository;
    private  final ItemRepository itemRepository;
    private  final ItemKeyRepository itemKeyRepository;
    private  final ItemKeyService itemKeyService;
    @Override
    public Map<String, Object> queryAll(TaskQueryCriteria criteria, Pageable pageable) {
        Page<Task> page = taskRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        return PageUtil.toPage(page.map(taskMapper::toDto));
    }

    @Override
    public List<TaskDto> queryAll(TaskQueryCriteria criteria) {
        return taskMapper.toDto(taskRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    @Transactional
    public TaskDto findById(Long id) {
        Task task = taskRepository.findById(id).orElseGet(Task::new);
        ValidationUtil.isNull(task.getId(), "Task", "id", id);
        return taskMapper.toDto(task);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TaskDto create(Task resources) {
        return taskMapper.toDto(taskRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Task resources) {
        Task task = taskRepository.findById(resources.getId()).orElseGet(Task::new);
        ValidationUtil.isNull(task.getId(), "Task", "id", resources.getId());
        task.copy(resources);
        taskRepository.save(task);
    }

    @Override
    public void deleteAll(Long[] ids) {
        for (Long id : ids) {
            taskRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<TaskDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (TaskDto task : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("序号", task.getId());
            map.put("物料编码", task.getItemKey().getItem().getCode());
            map.put("物料名称", task.getItemKey().getItem().getName());
            map.put("容器编号", task.getSrcStock()==null?"":task.getSrcStock().getCode());
            map.put("原点位", task.getSrcPointCode());
            map.put("目标点位", task.getDstPointCode());
            map.put("任务状态", task.getTaskStatus());
            map.put("计划数量", task.getPlanQty());
            map.put("移位数量", task.getMoveQty());
            map.put("创建人", task.getCreateBy());
            map.put("创建时间", task.getCreateTime());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public Task toEntity(TaskDto taskDto) {
        return taskMapper.toEntity(taskDto);
    }

    @Override
    public Task storeTask() {
        return null;
    }

    @Override
    public List<Task> getPickNotAllTask(Long id) {
        return taskRepository.getPickNotAllTask(id);
    }

    @Override
    public List<Task> getPickAllTask(Long id) {
        return taskRepository.getPickAllTask(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized void pickConfirm(long taskId, double pickedQuantity) throws Exception {
        if (taskId > 0) {
            TaskDto taskDto = findById(taskId);
            Task task = taskMapper.toEntity(taskDto);//Dto转实体
            if (task.getPlanQty() > task.getMoveQty()) {
                PickDetail pickDetail = task.getPickDetail();
                task.setMoveQty(pickedQuantity);
                task.setTaskStatus(BizStatus.FINISH);
                taskRepository.save(task);
                Inventory inv = inventoryRepository.findById(task.getInventory().getId()).get();
                if (inv != null) {
                    ItemKey itemKey = inv.getItemKey();
                    Item item = itemKey.getItem();
                    Dept dept = item.getDept();
                    double srcQty=inv.getQuantity();
                    inv.setQuantity(inv.getQuantity() - pickedQuantity);
                    inv.setQueuedQty(inv.getQueuedQty() - pickedQuantity);
                    inventoryRepository.save(inv);
                    if(inv.getQuantity()<=0){
                        inventoryRepository.delete(inv);
                    }
                    Stock stock=inv.getStock();
                    stock.setStatus(BaseStatus.FREE);
                    stockRepository.save(stock);
                    //添加库存日志
                    inventoryLogService.storeInventoryLog(BizStatus.PICK_DOWN,BizStatus.REDUCE,task.getPickDetail().getPo(),task.getItemKey(),task.getSrcPoint(),task.getDstPoint(),task.getSrcStock(),task.getDstStock(),srcQty,pickedQuantity, BizStatus.PICK,task.getId(),inv.getId(),"");

                    //刷新出库明细上的拣货数量
                    pickDetail.setPickedQty(pickDetail.getPickedQty() + pickedQuantity);
                    if (pickDetail.getOrderQty().equals(pickDetail.getPickedQty())) {
                        pickDetail.setStatus(BizStatus.PICK_ALL);
                    } else if (pickDetail.getAllocatedQty() > 0 && pickDetail.getOrderQty() - pickDetail.getPickedQty() > 0) {
                        pickDetail.setStatus(BizStatus.PICKUP);
                    }
                    pickDetailRepository.save(pickDetail);

                } else {
                    throw new RuntimeException("未找到库存相应记录！");
                }
            }

        } else {
            throw new RuntimeException("参数错误或为空");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized void pickBarBack(long taskId, double pickedQuantity) throws Exception {
        if (taskId > 0) {
            TaskDto taskDto = findById(taskId);
            Task task = taskMapper.toEntity(taskDto);//Dto转实体
            PickDetail pickDetail = task.getPickDetail();
            Inventory inv = inventoryRepository.findById(task.getInventory().getId()).get();
            if (inv != null) {
                //退回库存
                double srcQty=inv.getQueuedQty();
                inv.setQueuedQty(inv.getQueuedQty()+pickedQuantity);
                inv.setQuantity(inv.getQuantity()+pickedQuantity);
                inventoryRepository.save(inv);

                //添加库存日志
                inventoryLogService.storeInventoryLog(BizStatus.PICK_CANCEL,BizStatus.ADD,task.getPickDetail().getPo(),task.getItemKey(),task.getDstPoint(),task.getSrcPoint(),task.getSrcStock(),task.getDstStock(),srcQty,pickedQuantity, BizStatus.PICK,task.getId(),inv.getId(),"");


                //退回Task
                task.setMoveQty(task.getMoveQty() - pickedQuantity);
                taskRepository.save(task);

                //退回出库明细
                pickDetail.setPickedQty(pickDetail.getPickedQty() - pickedQuantity);
                if (pickDetail.getPickedQty() == 0) {
                    pickDetail.setStatus(BizStatus.ALLOCATE);
                }
                pickDetailRepository.save(pickDetail);
            } else {
                throw new RuntimeException("未找到库存相应记录！");
            }

        } else {
            throw new RuntimeException("参数错误或为空");
        }
    }

    @Transactional(readOnly = true)
    public  List<RPTaskList> queryTaskApp(IPTask t){
        String sql="SELECT t.pick_detail_id pickDetailId, it.code itemCode,it.`name` itemName,t.plan_qty qty,ik.prop_c1 pch,t.src_point_code srcPointCode,t.src_stock_code stockCode,t.dst_point_code dstPointCode\n" +
                " from data_task t\n" +
                "left join data_pick_detail d on t.pick_detail_id=d.id\n" +
                "left join data_item_key ik on ik.id=t.item_key_id\n" +
                "left join base_item it on it.id=ik.item_id\n" +
                "where d.`status`='ALLOCATE' \n" +
                "ORDER BY it.code";
        List ts= entityMapper.createNativeQuery(sql)
                .unwrap(SQLQuery.class)
                .setResultTransformer(
                        AliasToEntityMapResultTransformer.INSTANCE
                )
                .list();
        log.error(JSON.toJSONString(ts));
        List<RPTaskList> l = JSON.parseArray(JSON.toJSONString(ts),RPTaskList.class);
        return  l;
    }

    @Override
    public List<Task> findByPointCode(Long pointId) {
        String hql=" from Task t where t.dstPoint.id="+pointId+" and t.moveQty=0 ";
        Query query=entityMapper.createQuery(hql);
        List<Task> taskList=query.getResultList();
        return taskList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResult manualReceiving(String rfid,Point pointStart,int agvFlag) {
        ApiResult apiResult;
        String billTypeCode="";//单据类型
        Point pointEnd=null;
        // 解析RFID信息
        String itemCode=rfid.substring(0, 9);
        Item item=itemRepository.findByCode(itemCode);
        if (item==null){
            return ApiResult.result(500, "没有物料", "");
        }
        String propC1=rfid.substring(9, 11);
        String propC2=rfid.substring(11, 13);
        String propC3=rfid.substring(13, 19);// 系统单号
        Asn asn=asnRepository.findByRelatedBill1(propC3);
        if (!BizStatus.getBillToStock(asn.getBillType().getCode()).equals(item.getGoodType())){
            return ApiResult.fail(500,"单据类型和物料类型不匹配",null);
        }
        if (asn==null){
            return ApiResult.result(201, "没有入库单", "");
        }else {
            if (!asn.getStatus().equals(BizStatus.RECEIVING)&&!asn.getStatus().equals(BizStatus.ACTIVE)){
                return ApiResult.result(500, "入库单未激活", "");
            }
        }
        billTypeCode=asn.getBillType().getCode();//入库-单据类型
        String propC4=rfid.substring(19, 20);//供货商
        String propC5=Integer.valueOf(rfid.substring(20, 24),16)+"";//16进制 供货数量
        StringBuffer propC6 = new StringBuffer();//流水号
        StringBuffer propC7 = new StringBuffer();//成品物料码
        int xs = 0;//成品收货-箱数
        String propC6Title=null;//成品收货-成品码抬头
        /*Long propC6_start_d = 0l;//成品收货-成品码起始码
        Long propC6_end_d=0l;//成品收货-成品码终止码*/
        // 更新当前点位 存储容器状态
        String storageType="";
        if (billTypeCode.equals(BizStatus.FC_RK)) {
            //String tzm=rfid.substring(24,28);//特征码
            String sm=rfid.substring(28,50);//始码
            String zm=rfid.substring(50,72);//止码
            xs = Integer.parseInt(rfid.substring(72, 74),16);//箱数
            Integer xs_start_d = Integer.parseInt(rfid.substring(74,78));//成品包装箱起始码
            Integer xs_end_d = Integer.parseInt(rfid.substring(78,82));//成品包装箱终止码
            for (int i = xs_start_d; i <= xs_end_d; i++) {
                if (propC6.length()<1){
                    propC6.append(i);
                }else {
                    propC6.append(","+i);
                }
            }
            //String endm = rfid.substring(82,86);//结束吗

            //成品容器类型 入库
            storageType=BizStatus.CTP_STO;
        } else if (billTypeCode.equals(BizStatus.SM_RK)) {
            String lshBf=rfid.substring(24,rfid.length());
            int decimalMin = Integer.parseInt("0001", 16);//流水号范围
            int decimalMax = Integer.parseInt("EA60", 16);//流水号范围
            for (int i = 0; i < lshBf.length();) {
                String lsh=lshBf.substring(i,i+4);
                int decimalNumber = Integer.parseInt(lsh, 16);
                if (decimalNumber >= decimalMin && decimalNumber <= decimalMax) {
                    if (propC6.length() < 1) {
                        propC6.append(lsh);
                    } else {
                        propC6.append(",");
                        propC6.append(lsh);
                    }
                } else {
                    System.out.println("无效RFID:" + lsh);
                }
                i=i+4;
            }
            //半成品 入库
            storageType=BizStatus.TP_STO;
        } else if (billTypeCode.equals(BizStatus.RM_RK)) {
            String lshBf=rfid.substring(24,rfid.length());
            int decimalMin = Integer.parseInt("0001", 16);//流水号范围
            int decimalMax = Integer.parseInt("EA60", 16);//流水号范围
            for (int i = 0; i < lshBf.length();) {
                String lsh=lshBf.substring(i,i+4);
                int decimalNumber = Integer.parseInt(lsh, 16);
                if (decimalNumber >= decimalMin && decimalNumber <= decimalMax) {
                    if (propC6.length() < 1) {
                        propC6.append(decimalNumber);
                    } else {
                        propC6.append(",");
                        propC6.append(decimalNumber);
                    }
                } else {
                    System.out.println("无效RFID:" + lsh);
                }
                i=i+4;
            }
            //料箱 入库
            if (pointStart.getArea().getId()==45){
                storageType=BizStatus.LXZ_STO;
            }else {
                storageType=BizStatus.LX_STO;
            }
        }
        if (agvFlag==1) {
            String stockTypeCode="";
            if (billTypeCode.equals(BizStatus.RM_RK)){
                stockTypeCode=BizStatus.LX;
            }else if (billTypeCode.equals(BizStatus.SM_RK)){
                stockTypeCode=BizStatus.BCP;
            }else if (billTypeCode.equals(BizStatus.FC_RK)){
                stockTypeCode=BizStatus.CP;
            }
            // 分配目标库位
            List<Point> pointEndList = pointRepository.findByCpAreaCode(stockTypeCode);
            if (pointEndList.size() > 0) {
                pointEnd = pointEndList.get(0);
            } else {
                return ApiResult.fail(500, "没有可用存储库位", null);
            }
        }

        ItemKey itemKey=itemKeyRepository.getByItemKeyPro7(rfid);
        if (itemKey==null){
            itemKey = itemKeyService.getItemKey(item, propC1, propC2, propC3, propC4, propC5, propC6.toString(), rfid);
        }else if (itemKey.getEnabled()==false){
            itemKey.setEnabled(true);
            itemKeyRepository.save(itemKey);
        }else {
            return ApiResult.result(500, "重复读取", "");
        }
        // 已生成ItemKey
        {
            //获取流水号
            String[] lsh = itemKey.getPropC6().split(",");
            int taskSum = 0;// 生成task数量
            if (asn.getBillType().getCode().equals(BizStatus.FC_RK)) {
                taskSum = 1;//按 一张rfid生成一个task
            } else {
                if (lsh.length != itemKey.getIntPropC5()) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return ApiResult.result(500, "流水号数量和供货数量不一致", "");
                }
                taskSum = 1;//按 一张rfid生成一个task
            }
            // 更新收货明细
            List<AsnDetail> asnDetailList=asnDetailRepository.findByAsnAndItem(asn.getRelatedBill1(), itemCode);
            int asnQty = Integer.parseInt(propC5, 16);//收货数量
            if(asnDetailList.size()<1){
                return ApiResult.fail(500,"收货单中没有对应物料",null);
            }
            boolean adFlag=false;
            for (int i = 0; i < asnDetailList.size(); i++) {
                AsnDetail asnDetail=asnDetailList.get(i);
                if (!BizStatus.getBillToStock(asnDetail.getAsn().getBillType().getCode()).equals(item.getGoodType())){
                    return ApiResult.fail(500,"收货单类型错误",null);
                }
                if (asnDetail.getOrderQty()-asnDetail.getReceivedQty()>=asnQty){
                    asnDetail.setReceivedQty(asnDetail.getReceivedQty()+asnQty);
                    asnDetailRepository.save(asnDetail);
                    adFlag=true;
                    break;
                }
            }
            if (adFlag==false){
                return ApiResult.fail(500,"入库单剩余收货数量小于当前收货数量",null);
            }
            for (int i = 0; i < taskSum; i++) {
                Task task = new Task();
                task.setPlanQty(Double.valueOf(propC5));//收货数量
                /*if (asn.getBillType().getCode().equals(BizStatus.FC_RK)) {
                    *//*task.setPlanQty(Double.valueOf(Integer.parseInt(propC5, 16)));//收货数量

                    StringBuffer putCode = new StringBuffer();
                    for (int j = xs_start_d; j <=xs_end_d ; j++) {
                        if (putCode.length()<1){
                            putCode.append(j);
                        }
                    }*//*
//                    propC6_start_d = propC6_start_d + xs_d;
//                    task.setPutCode(putCode.toString());//流水号 起止码
                } else {
                    task.setPutCode(propC6.toString());
                }*/
                task.setPutCode(propC6.toString());
                task.setItemKey(itemKey);
                task.setDept(UserUtils.getDept());
                task.setTaskStatus(BizStatus.RECEIVING);
                task.setBeSkip(agvFlag);
                task.setBillCode(propC3);
                task.setTaskType(asn.getBillType().getCode());
                task.setSrcPoint(pointStart);
                if (pointEnd==null){
                    task.setDstPoint(pointStart);
                }else {
                    task.setDstPoint(pointEnd);
                }
                taskRepository.save(task);
            }
        }

        if (agvFlag==1) {
            /** AGV人工入库*/
            pointStart.setStorageType(storageType);
            pointRepository.save(pointStart);
            if (pointEnd.getArea().getId()==39&&pointEnd.getType().equals(BaseStatus.STORAGE)){
                pointEnd.setStorageType(BizStatus.LX_STO);
            }else {
                pointEnd.setStorageType(storageType);
            }
            pointRepository.save(pointEnd);
            return ApiResult.result(200, "操作成功", billTypeCode);
        }else {
            /** 人工入库*/
            Point point=pointStart;
            point.setStorageType(storageType);
            pointRepository.save(point);
            // 生成库存
            Inventory inventory = addAsnInventory(billTypeCode, point,null,0l,itemKey.getId());
        }
        return ApiResult.result(200, "操作成功", null);
    }
    /** 入库-生成库存*/
    public Inventory addAsnInventory(String billTypeCode, Point point, Integer agvTaskId,Long agvFlag,Long itemKeyId) {
        List<Map<String, Object>> taskMapList = taskRepository.findByAgvTask(agvTaskId, billTypeCode, agvFlag,itemKeyId);
        Inventory inventory = inventoryService.asnAddInventory(taskMapList);
        if (point.getStatus().equals(BaseStatus.USED)) {
            point.setStatus(BaseStatus.FREE);
        } else {
            // 人工入库没有选中推荐库位，清除一个库位的占用状态
            List<Point> pointList = pointRepository.findByAreaCodeCp(inventory.getItemKey().getItem().getGoodType(), BaseStatus.USED);
            for (int i = 0; i < pointList.size(); i++) {
                Point pointUsed = pointList.get(0);
                if (point.getHeat() == null || point.getHeat() == 1) {
                    //浅位 直接取消
                    pointUsed.setStatus(BaseStatus.FREE);
                } else {
                    // 深位，查询浅位是否空闲
                    List<Point> pointListQ = pointRepository.findByBeatCode(point.getBeatCode(), point.getHeat());
                    if (pointListQ.size() > 0) {
                        // 浅位空闲
                        continue;
                    } else {
                        pointUsed.setStatus(BaseStatus.FREE);
                    }
                }
                pointRepository.save(pointUsed);
                break;
            }
        }
        pointRepository.save(point);
        return inventory;
    }

    public List<Object[]> queryAreaMonth(String type) {
        List<Object[]> taskList=null;
        String hql = "";
        if(type.equals("IN")){
            hql += " select t.dstPoint.area.name,count(t.id) from Task t where  t.dstPoint.area.name in ('"+AreaNameDic.QHTL+"','"+AreaNameDic.QHTK+"','"+AreaNameDic.ZCK+"','"+AreaNameDic.ZCM+"')";
            hql+=" and t.asnDetail.id is not null ";
            hql+=" group by  t.dstPoint.area.name";
        }else if(type.equals("OUT")){
            hql += " select t.srcPoint.area.name,count(t.id) from Task t where  t.srcPoint.area.name in ('"+AreaNameDic.QHTL+"','"+AreaNameDic.QHTK+"','"+AreaNameDic.ZCK+"','"+AreaNameDic.ZCM+"')";
            hql+=" and t.pickDetail.id is not null ";
            hql+=" group by  t.srcPoint.area.name";
        }
        Query query = entityMapper.createQuery(hql);
        taskList = query.getResultList();
        return taskList;
    }

    public List<Object[]> queryAreaDay(String type,String zoneType) {
        List<Object[]> taskList=null;
        String hql = "select count(t.id),CAST(sum(t.moveQty) as integer )from Task t where 1=1";
        if(type.equals("IN")){
            if(zoneType.equals("ZC")) {
                hql += " and t.dstPoint.area.name in ('" + AreaNameDic.ZCM + "')";
            }
            hql+=" and t.asnDetail.id is not null ";
        }else if(type.equals("OUT")){
            if(zoneType.equals("ZC")) {
                hql += " and t.srcPoint.area.name in ('" + AreaNameDic.ZCM + "')";
            }
            hql+=" and t.pickDetail.id is not null ";
        }
        hql += " and DATE_FORMAT(t.createTime,'%Y-%m-%d')=DATE_FORMAT(now(),'%Y-%m-%d')";
        Query query = entityMapper.createQuery(hql);
        taskList = query.getResultList();
        return taskList;
    }

    public ApiResult getAsnTask(Point endPoint, Task task) {
        task.setDstPoint(endPoint);
        task.setMoveQty(task.getPlanQty());
        taskRepository.save(task);
        List<AsnDetail> asnDetailList=asnDetailRepository.findByAsnAndItem(task.getBillCode(), task.getItemKey().getItem().getCode());
        if (asnDetailList.size()>0){
            AsnDetail asnDetail=asnDetailList.get(0);
            asnDetailService.receivingAsnDetail(asnDetail, task.getMoveQty());
        }else {
            return ApiResult.success(500, "收货单异常！！", "");
        }
        return null;
    }

    @Override
    public ApiResult picking(Long[] ids) {
        List<Task> taskList=new ArrayList<>();
        for (int i = 0; i < ids.length; i++) {
            Long id=ids[i];
            Task task=taskRepository.getById(id);
            taskList.add(task);
            if (task.getAgvTask()!=null){
                AgvTask agvTask=task.getAgvTask();
                if (agvTask.getStatus().equals(BizStatus.OPEN)||agvTask.getStatus().equals(BizStatus.ATWORK)){
                    return ApiResult.fail(500,"AGV搬运任务未完成",task);
                }
            }
        }
        inventoryService.pickDelInventory(taskList);
        return ApiResult.fail(200,"拣货成功","");
    }

    @Override
    public ApiResult devanRfidAsn(String rfid,String pointType) {
        JSONObject data=new JSONObject();
        if (rfid.length()>24){
            String sku=rfid.substring(0, 9)+"";//sku
            Item item=itemRepository.findByCode(sku);
            if (item.getGoodType().equals(BizStatus.CP)){
                rfid=rfid.substring(0,86);
            }
            String propC1=rfid.substring(9, 11)+"";
            String propC2=rfid.substring(11, 13)+"";
            String propC3=rfid.substring(13, 19)+"";// 系统单号
            String propC5=rfid.substring(20, 24)+"";// 收货数量（16禁止）

            Asn asn=asnRepository.findByRelatedBill1(propC3);
            if (asn!=null){
                String billTypeCode=asn.getBillType().getCode();
                data.put("relatedBill1",asn.getRelatedBill1());
                data.put("relatedBill2",asn.getRelatedBill2());
                data.put("billType",asn.getBillType());
                data.put("sku",sku);
                data.put("RFID",rfid);
                List<AsnDetail> asnDetailList = asnDetailRepository.findByAsnAndItem(asn.getRelatedBill1(),sku);
                if (asnDetailList.size()<1){
                    return ApiResult.fail(500,"未查询到入库信息",data);
                }
                double orderQty=0;
                for (int i = 0; i < asnDetailList.size(); i++) {
                    orderQty=orderQty+(asnDetailList.get(i).getOrderQty()-asnDetailList.get(i).getReceivedQty());
                }
                data.put("orderQty",orderQty);
                data.put("lineNos",asnDetailList.size());
                data.put("receivedQty",Integer.parseInt(propC5, 16));
                String areaCode="";
                if (billTypeCode.equals(BizStatus.FC_RK)){
                    // 成品条码解析
                    if (rfid.length()==86){
                        areaCode=BizStatus.CP;
                    }else {
                        return ApiResult.fail(400,"rfid长度不为86","");
                    }
                }else if (billTypeCode.equals(BizStatus.RM_RK)){
                    areaCode=BizStatus.LX;
                }else if (billTypeCode.equals(BizStatus.SM_RK)){
                    // 半成品入库
                    areaCode=BizStatus.BCP;
                }
                data.put("billCode",areaCode);
                // 查询推荐库位
                List<Point> pointEndList = pointRepository.getTjPointList(areaCode, pointType);
                String pointCode="";
                if (pointEndList.size()>0){
                    pointCode=pointEndList.get(0).getCode();
                }
                data.put("pointCode",pointCode);
            }else {
                return ApiResult.fail(400,"未查询到系统单号","");
            }
        }
        return ApiResult.fail(200,"操作成功",data);
    }

    @Override
    public ApiResult devanRfidPT(String rfid) {
        JSONObject data=new JSONObject();
        String sku=rfid.substring(0, 9);// sku
        Item item=itemRepository.findByCode(sku);
        if (item==null){
            return ApiResult.fail(400,"没有找到物料",null);
        }
        // 成品解析
        ItemKey itemKey=itemKeyRepository.getByItemKeyPro7(rfid);
        if (itemKey==null){
            return ApiResult.fail(400,"没有找到RFID码对应的库存",null);
        }
        Inventory inventory=inventoryRepository.findByItemKey(itemKey.getId());
        if (inventory==null){
            return ApiResult.fail(500,"库存异常",null);
        }

        if (inventory.getQueuedQty()<=0){
            // 未分配
            data.put("sku",sku);
            data.put("RFID",rfid);
            data.put("invId",inventory.getId());
            return ApiResult.fail(201,"库存未进行分配，请选择需要出库出库单",data);
        }else {
            // 已分配
            data.put("sku",sku);
            data.put("RFID",rfid);
            data.put("invId",inventory.getId());
            data.put("receivedQty",inventory.getQueuedQty());
            /** 查询关联Task任务*/
            List<Task> taskList=taskRepository.findByItemKey(itemKey.getId(), BizStatus.ALLOCATE);
            Task task=taskList.get(0);
            PickDetail pickDetail=task.getPickDetail();
            Pick pick=pickDetail.getPick();
            // 已占用库存 推荐库存
            data.put("relatedBill1",pick.getRelatedBill1());
            data.put("relatedBill2",pick.getRelatedBill2());
            data.put("billType",pick.getBillType());
            data.put("pdId",pickDetail.getId());
            data.put("taskId",task.getId());
            data.put("orderQty",pickDetail.getAllocatedQty()-pickDetail.getPickedQty());
        }
        if (item.getGoodType().equals(BizStatus.CP)){

        }else if (item.getGoodType().equals(BizStatus.BCP)){

        }else if (item.getGoodType().equals(BizStatus.LX)){
            // 料箱解析
        }else {
            return ApiResult.fail(400,"请维护物料类型，无法识别解析方式",null);
        }
        return ApiResult.fail(200, "操作成功", data);
    }

    @Override
    public ApiResult butSTputaway(Long taskId, Long pointId) {
        Task task=taskRepository.getById(taskId);
        /** 料箱上架,添加库存*/
        Inventory inventory = addAsnInventory(BizStatus.RM_RK, task.getDstPoint(), task.getAgvTask().getId(),1l,task.getItemKey().getId());
        /** 库存移位*/
        if (!task.getDstPoint().getId().equals(pointId)){
            // 目标位
            Point pointEnd=pointRepository.getById(pointId);
            // 起点位
            Point pointStart=inventory.getPoint();
            // 移位
            //写入终点
            if (pointEnd.getArea().getId()==39&&pointEnd.getType().equals(BaseStatus.STORAGE)){
                pointEnd.setStorageType(BizStatus.LX_STO);
            }else {
                pointEnd.setStorageType(pointStart.getStorageType());
            }
            pointRepository.save(pointEnd);
            //释放起点
            pointStart.setStorageType(null);
            pointRepository.save(pointStart);
            //更新库存位置
            inventory.setPoint(pointEnd);
            inventoryRepository.save(inventory);
            /** 添加库存日志-移位*/
            inventoryLogService.storeInventoryLog(BizStatus.MOVE,BizStatus.ADD,inventory.getItemKey().getPropC3(),inventory.getItemKey(),pointStart,inventory.getPoint(),null,null,0d,inventory.getQuantity(), inventory.getItemKey().getPropC6(),null,inventory.getId(),"");
        }
        return ApiResult.fail(200,"上架成功",null);
    }

    @Override
    public ApiResult rmCkPickUp(JSONArray taskIds) {
        AgvTask agvTask = null;
        for (int i = 0; i < taskIds.size(); i++) {
            Task task=taskRepository.getById(taskIds.getLong(i));
            if (i==0){
                String storageType=null;
                String startPointCode=null;
                if (task.getSrcPoint().getArea().getId()==39&&task.getSrcPoint().getType().equals(BaseStatus.STORAGE)){
                    storageType=BizStatus.LXZ_STO;
                    startPointCode=task.getDstPoint().getBeatCode();
                }
                // 第一个任务 先生成AgvTask任务
                agvTask = agvTaskService.addAgvTask(BizStatus.AGV, storageType, startPointCode, task.getDstPoint().getCode(), BizStatus.OPEN, BizStatus.PICK);
            }
            task.setAgvTask(agvTask);
            taskRepository.save(task);
        }
        return ApiResult.fail(200,"生成搬运任务:"+agvTask.getId(),null);
    }

}
