/*
 *  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.youchain.basicdata.domain.*;
import com.youchain.basicdata.repository.StockRepository;
import com.youchain.basicdata.service.PointService;
import com.youchain.basicdata.service.StockService;
import com.youchain.businessdata.domain.*;
import com.youchain.businessdata.inputJson.IPTask;
import com.youchain.businessdata.inputJson.IScanPut;
import com.youchain.businessdata.inputJson.buttenJson.PickOutButton;
import com.youchain.businessdata.inputJson.buttenJson.PickTicketButton;
import com.youchain.businessdata.repository.*;
import com.youchain.businessdata.returnJson.RPPickList;
import com.youchain.businessdata.returnJson.RPTaskList;
import com.youchain.businessdata.returnJson.RRkXpp;
import com.youchain.businessdata.service.*;
import com.youchain.businessdata.service.dto.*;
import com.youchain.businessdata.service.mapstruct.TaskLogMapper;
import com.youchain.businessdata.service.mapstruct.TaskMapper;
import com.youchain.exception.BadRequestException;
import com.youchain.modules.system.domain.Job;
import com.youchain.modules.system.repository.JobRepository;
import com.youchain.utils.*;
import lombok.RequiredArgsConstructor;
import com.youchain.businessdata.service.mapstruct.PickTicketMapper;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.SQLQuery;
import org.hibernate.transform.AliasToEntityMapResultTransformer;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.io.IOException;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.servlet.http.HttpServletResponse;

/**
 * @author JiangKun
 * @website https://eladmin.vip
 * @description 服务实现
 * @date 2024-01-11
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class PickTicketServiceImpl implements PickTicketService {

    private final PickTicketRepository pickTicketRepository;
    private final PickTicketMapper pickTicketMapper;
    private final PickDetailRepository pickDetailRepository;
    private final CodeUtils codeUtils;
    private final TaskService taskService;
    private final InventoryService inventoryService;
    private final TaskLogService taskLogService;
    private final InventoryLogService invLogService;
    private final PickDetailService pickDetailService;
    private final InventoryRepository inventoryRepository;
    private final TaskMapper taskMapper;
    private final TaskLogRepository taskLogRepository;
    private final TaskLogMapper taskLogMapper;
    private final StockRepository stockRepository;
    private final XppRecordRepository xppRecordRepository;
    private final XppRecordService xppService;
    private final PickOutService pickOutService;
    private final EntityManager entityManager;
    private final XppRecordService xppRecordService;
    private final PointService pointService;
    private final JobRepository jobRepository;

    @Override
    public Map<String, Object> queryAll(PickTicketQueryCriteria criteria, Pageable pageable) {
        Page<PickTicket> page = pickTicketRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        return PageUtil.toPage(page.map(pickTicketMapper::toDto));
    }

    @Override
    public List<PickTicketDto> queryAll(PickTicketQueryCriteria criteria) {
        return pickTicketMapper.toDto(pickTicketRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    @Transactional
    public PickTicketDto findById(Long id) {
        PickTicket pickTicket = pickTicketRepository.findById(id).orElseGet(PickTicket::new);
        ValidationUtil.isNull(pickTicket.getId(), "PickTicket", "id", id);
        return pickTicketMapper.toDto(pickTicket);
    }

    @Override
    @Transactional
    public PickTicket getEntity(Long id) {
        PickTicket pickTicket = pickTicketRepository.findById(id).orElseGet(PickTicket::new);
        return pickTicket;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PickTicketDto create(PickTicket resources) {
        return pickTicketMapper.toDto(pickTicketRepository.save(resources));
    }

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

    @Override
    public void deleteAll(Long[] ids) {
        for (Long id : ids) {
            PickTicketDto byId = this.findById(id);
            //删除管理字段
            List<PickDetail> pickDetails = pickDetailRepository.queryByPickTicketId(id);
            if (pickDetails.isEmpty()) {
                for (PickDetail p : pickDetails) {
                    if(p.getAllocatedQty()>0){
                        throw new BadRequestException(HttpStatus.NOT_FOUND, "已出单，不能删除");
                    }
                    if (p.getPickTicket().getBillType().equals(BaseStatus.BT_QTCK) && p.getPickTicket().getStatus().equals(BizStatus.ALLOCATE)) {
                        //调用取消分配
                        PickTicketButton pickTicketButton = new PickTicketButton();
                        pickTicketButton.setPickConfirmNo(4);
                        pickTicketButton.setPickTicketId(p.getPickTicket().getId());
                        this.pickingOperation(pickTicketButton);
                    }
                    if (byId.getStatus().equals(BizStatus.OPEN)) {
                        pickDetailRepository.deleteById(p.getId());
                    } else {
                        throw new BadRequestException(HttpStatus.NOT_FOUND, "单号:" + byId.getCode() + "打开状态才能删除");
                    }
                }
            }
            pickTicketRepository.deleteById(id);
        }
    }

    public void deletePickTicket(Long[] ids) {
        for (Long id : ids) {
           //循环明细进行删除
            List<PickDetail> ds=pickDetailRepository.queryByPickTicketId(id);
            for(PickDetail d:ds) {
                pickDetailService.deletePickDetail(d.getId());
            }
            pickTicketRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<PickTicketDto> all, HttpServletResponse response) throws Exception {
        List<Map<String, Object>>  list=ExcelDownUtils.CreateMap(all,"PickTicket");
        FileUtil.downloadExcel(list, response);
    }


    @Override
    public PickTicket storePick(BillType bt, Area shArea, Area outArea, String bpType, String jhCode) {
        PickTicket p = new PickTicket();
        p.setCode(codeUtils.getCode_yyMMdd(bt.getPrefix(), 3));
        p.setBillType(bt);
        p.setShArea(shArea);
        p.setArea(outArea);
        p.setDept(UserUtils.getDept());
        p.setOrderDate(new Timestamp(System.currentTimeMillis()));
        p.setBpType(bpType);
        p.setDept(UserUtils.getDept());
        p.setRelatedBill1(jhCode);
        p.setCusCode(jhCode);
        p.setStatus(BizStatus.OPEN);
        pickTicketRepository.save(p);
        return p;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void pickingOperation(PickTicketButton pickTicketButton) {
        //拣货按钮
        int pickConfirmNo = pickTicketButton.getPickConfirmNo();
        PickTicketDto pickTicketDto = this.findById(pickTicketButton.getPickTicketId());
        switch (pickConfirmNo) {
            case 1:
                //整单拣货
                //根据单号查全部的task数据
                TaskQueryCriteria taskQueryCriteria = new TaskQueryCriteria();
                taskQueryCriteria.setBillCode(pickTicketDto.getCode());
                List<TaskDto> taskDtos = taskService.queryAll(taskQueryCriteria);
                if (taskDtos.isEmpty()) {
                    throw new BadRequestException(HttpStatus.NOT_FOUND, pickTicketDto.getCode() + "单子,未查到分配的任务");
                }
                //总拣货数量
                double planQtySum = 0d;
                for (TaskDto taskDto : taskDtos) {//所有的数据
                    if (taskDto.getMoveQty() > 0) {
                        //剩余数量
                        double syNum = taskDto.getPlanQty() - taskDto.getMoveQty();
                        if (syNum == 0) {
                            break;
                        } else {
                            PickTicketButton pickTicketButton1 = new PickTicketButton();
                            pickTicketButton1.setPickConfirmNo(2);
                            Long[] longs = new Long[1];
                            longs[0] = taskDto.getId();
                            pickTicketButton1.setTaskId(longs);
                            pickTicketButton1.setOnePickConfirmNumber((int) syNum);
                            pickTicketButton1.setPickTicketId(pickTicketButton.getPickTicketId());
                            this.pickingOperation(pickTicketButton1);
                            break;
                        }
                    }
                    //根据task扣除库存（srcpoint，itemkey，pick表上的库区三个字段查找库存），找到则减少相应的数量及占用数量。生成对应的taskLog表，
                    List<Inventory> inventories = inventoryService.queryInventory(pickTicketDto.getArea().getId(), taskDto.getSrcPoint().getId(), taskDto.getItemKey().getId());
                    if (inventories.isEmpty()) {
                        throw new BadRequestException(HttpStatus.NOT_FOUND, taskDto.getItem().getCode() + "未发现库存数据");
                    }
                    //减少相应的数量及占用数量    减分配数量planQty
                    Inventory inventory = inventories.get(0);
                    //扣除后的数量
                    double subNum = inventory.getQuantity() - taskDto.getPlanQty();
                    double kcNum = taskDto.getPlanQty();
                    if (subNum < 0) {
                        throw new BadRequestException(HttpStatus.NOT_FOUND, "拣货数量大于库存数量");
                    }
                    if (subNum > 0) {
                        //库存扣除后还要  inventoryLog
                        invLogService.storeInventoryLog(BizStatus.PICK_DOWN, BizStatus.REDUCE, null, inventory.getArea(), inventory.getItemKey(), inventory.getPoint(), inventory.getPoint(), inventory.getStock(), inventory.getStock(), inventory.getQuantity(), taskDto.getPlanQty(),
                                null, null, BizStatus.PICK_DOWN, inventory.getId(), inventory.getId(), inventory.getDescription());
                        //生成taskLog 日志
                        taskLogService.createTaskLogData(taskDto, taskDto.getPlanQty());
                        //task的修改
                        //拣货数量
                        taskDto.setMoveQty(taskDto.getPlanQty());
                        taskDto.setTaskStatus(BizStatus.PICK_ALL);
                        taskService.update(taskMapper.toEntity(taskDto));
                        //库存的修改
                        inventory.setQuantity(subNum);
                        inventory.setQueuedQty(inventory.getQueuedQty() - taskDto.getPlanQty());
                        //存储拣货确认的库存数据
                        Task task = taskMapper.toEntity(taskDto);
                        Inventory inventory1 = inventoryService.getInventory(inventory.getItemKey(), inventory.getArea(), task.getDstPoint(), task.getZzkw(),  inventory.getDept(), BizStatus.RECEIVING_UP,task.getDstStockCode());
                        invLogService.storeInventoryLog(BizStatus.PICK_DOWN, BizStatus.ADD, task.getBillCode(), inventory1.getArea(), inventory1.getItemKey(), inventory1.getPoint(), inventory1.getPoint(), inventory1.getStock(), inventory1.getStock(), inventory1.getQuantity(), kcNum,
                                null, null, BizStatus.PICK_DOWN, inventory1.getId(), inventory1.getId(), inventory1.getDescription());
                        inventory1.setQuantity(inventory1.getQuantity() + kcNum);
                        inventory1.setQueuedQty(inventory1.getQueuedQty() + kcNum);
                        inventoryService.update(inventory1);
                        inventoryService.update(inventory);
                    } else {
                        //库存扣除完
                        invLogService.storeInventoryLog(BizStatus.PICK_DOWN, BizStatus.REDUCE, null, inventory.getArea(), inventory.getItemKey(), inventory.getPoint(), inventory.getPoint(), inventory.getStock(), inventory.getStock(), inventory.getQuantity(), taskDto.getPlanQty(),
                                null, null, BizStatus.PICK_DOWN, inventory.getId(), inventory.getId(), inventory.getDescription());
                        //生成taskLog 日志
                        taskDto.setMoveQty(taskDto.getPlanQty());
                        taskDto.setTaskStatus(BizStatus.PICK_ALL);
                        taskService.update(taskMapper.toEntity(taskDto));
                        taskLogService.createTaskLogData(taskDto, taskDto.getPlanQty());
                        //存储拣货确认的库存数据
                        Task task = taskMapper.toEntity(taskDto);
                        Inventory inventory1 = inventoryService.getInventory(inventory.getItemKey(), inventory.getArea(), task.getDstPoint(), task.getZzkw(),  inventory.getDept(), BizStatus.RECEIVING_UP,task.getDstStockCode());
                        invLogService.storeInventoryLog(BizStatus.PICK_DOWN, BizStatus.ADD, task.getBillCode(), inventory1.getArea(), inventory1.getItemKey(), inventory1.getPoint(), inventory1.getPoint(), inventory1.getStock(), inventory1.getStock(), inventory1.getQuantity(), kcNum,
                                null, null, BizStatus.PICK_DOWN, inventory1.getId(), inventory1.getId(), inventory1.getDescription());
                        inventory1.setQuantity(inventory1.getQuantity() + kcNum);
                        inventory1.setQueuedQty(inventory1.getQueuedQty() + kcNum);
                        inventoryService.update(inventory1);
                        inventoryRepository.delete(inventory);
                    }
//                    PickDetail pickDetail = pickDetailRepository.queryByPickTicketIdItemId(pickTicketDto.getId(), taskDto.getItem().getId());
                    PickDetail pickDetail = pickDetailRepository.getById(taskDto.getPickDetail().getId());
                    if (Objects.isNull(pickDetail)) {
                        throw new BadRequestException(HttpStatus.NOT_FOUND, taskDto.getItem().getCode() + "未查到明细数据");
                    }
                    pickDetail.setPickedQty(taskDto.getPlanQty());
                    //回写 pickdetail 上的拣货数量
                    pickDetailService.update(pickDetail);
                    planQtySum += taskDto.getPlanQty();
                }
                // 数量按照实际扣减数量写入，并生成inventoryLog记录。pickdetail和pick上的拣货数量相应增加
                //拣货数量
                pickTicketDto.setPickedQuantity(pickTicketDto.getPickedQuantity() + planQtySum);
                pickTicketDto.setBhQty(pickTicketDto.getBhQty() + planQtySum);
                //发运数量
                //pickTicketDto.setShippedQuantity(planQtySum);
//                pickTicketDto.setStatus(BizStatus.PICK_ALL);
                if ((pickTicketDto.getOrderQuantity() - pickTicketDto.getPickedQuantity()) == 0) {
                    pickTicketDto.setStatus(BizStatus.PICK_ALL);
                } else {
                    pickTicketDto.setStatus(BizStatus.PICKUP);
                }
                //备货日期（拣货写）
                pickTicketDto.setStockingDate(new Timestamp(new Date().getTime()));
                this.update(pickTicketMapper.toEntity(pickTicketDto));
                break;
            case 2:
                //单一拣货
                //输入的容器
                String stockCode = null;
                if (pickTicketButton.getStockCode() != null && !pickTicketButton.getStockCode().isEmpty()) {
                    stockCode = pickTicketButton.getStockCode();
                }
                //单一收货输入的数量
                double pickQty = pickTicketButton.getOnePickConfirmNumber();
                pickForTask(pickTicketButton.getTaskId()[0], stockCode, pickQty, null, null);
                break;
            case 3:
                //批量拣货
                Long[] taskIds = pickTicketButton.getTaskId();
                for (Long taskId1 : taskIds) {
                    TaskDto taskDto1 = taskService.findById(taskId1);
                    if (taskDto1.getMoveQty() > 0) {
                        //剩余数量
                        double syNum = taskDto1.getPlanQty() - taskDto1.getMoveQty();
                        if (syNum == 0) {
                            break;
                        } else {
                            PickTicketButton pickTicketButton1 = new PickTicketButton();
                            pickTicketButton1.setPickConfirmNo(2);
                            Long[] longs = new Long[1];
                            longs[0] = taskDto1.getId();
                            pickTicketButton1.setTaskId(longs);
                            pickTicketButton1.setOnePickConfirmNumber((int) syNum);
                            pickTicketButton1.setPickTicketId(pickTicketButton.getPickTicketId());
                            this.pickingOperation(pickTicketButton1);
                            break;
//                            throw new BadRequestException(HttpStatus.NOT_FOUND, taskDto.getItem().getCode() + "已经单一拣货");
                        }
                    }
//                    if (taskDto1.getMoveQty()>0){
//                        throw new BadRequestException(HttpStatus.NOT_FOUND, taskDto1.getItem().getCode() + "已经单一拣货");
//                    }
                    //根据task扣除库存（srcpoint，itemkey，pick表上的库区三个字段查找库存），找到则减少相应的数量及占用数量。生成对应的taskLog表，
                    List<Inventory> inventories1 = inventoryService.queryInventory(pickTicketDto.getArea().getId(), taskDto1.getSrcPoint().getId(), taskDto1.getItemKey().getId());
                    if (inventories1.isEmpty()) {
                        throw new BadRequestException(HttpStatus.NOT_FOUND, taskDto1.getItem().getCode() + "未发现库存数据");
                    }
                    //减少相应的数量及占用数量    减分配数量planQty
                    Inventory inventory1 = inventories1.get(0);
                    //扣除后的数量
                    double subNum1 = inventory1.getQuantity() - taskDto1.getPlanQty();
                    double kcNum1 = taskDto1.getPlanQty();
                    if (subNum1 < 0) {
                        throw new BadRequestException(HttpStatus.NOT_FOUND, "拣货数量大于库存数量");
                    }
                    if (subNum1 > 0) {
                        //库存扣除后还要  inventoryLog
                        invLogService.storeInventoryLog(BizStatus.PICK_DOWN, BizStatus.REDUCE, null, inventory1.getArea(), inventory1.getItemKey(), inventory1.getPoint(), inventory1.getPoint(), inventory1.getStock(), inventory1.getStock(), inventory1.getQuantity(), taskDto1.getPlanQty(),
                                null, null, BizStatus.PICK_DOWN, inventory1.getId(), inventory1.getId(), inventory1.getDescription());
                        //生成taskLog 日志
                        taskLogService.createTaskLogData(taskDto1, taskDto1.getPlanQty());
                        //task的修改
                        taskDto1.setMoveQty(taskDto1.getPlanQty());
                        taskDto1.setTaskStatus(BizStatus.PICK_ALL);
                        taskService.update(taskMapper.toEntity(taskDto1));
                        //库存的修改
                        inventory1.setQuantity(subNum1);
                        inventory1.setQueuedQty(inventory1.getQueuedQty() - taskDto1.getPlanQty());
                        //存储拣货确认的库存数据
                        Task task = taskMapper.toEntity(taskDto1);
                        Inventory inventory11 = inventoryService.getInventory(inventory1.getItemKey(), inventory1.getArea(), task.getDstPoint(), task.getZzkw(), inventory1.getDept(), BizStatus.RECEIVING_UP,task.getDstStockCode());
                        invLogService.storeInventoryLog(BizStatus.PICK_DOWN, BizStatus.ADD, null, inventory11.getArea(), inventory11.getItemKey(), inventory11.getPoint(), inventory11.getPoint(), inventory11.getStock(), inventory11.getStock(), inventory11.getQuantity(), kcNum1,
                                null, null, BizStatus.PICK_DOWN, inventory11.getId(), inventory11.getId(), inventory11.getDescription());
                        inventory11.setQuantity(inventory11.getQuantity() + kcNum1);
                        inventory11.setQueuedQty(inventory11.getQueuedQty() + kcNum1);
                        inventoryService.update(inventory11);
                        inventoryService.update(inventory1);
                    } else {
                        //库存扣除完
                        invLogService.storeInventoryLog(BizStatus.PICK_DOWN, BizStatus.REDUCE, null, inventory1.getArea(), inventory1.getItemKey(), inventory1.getPoint(), inventory1.getPoint(), inventory1.getStock(), inventory1.getStock(), inventory1.getQuantity(), taskDto1.getPlanQty(),
                                null, null, BizStatus.PICK_DOWN, inventory1.getId(), inventory1.getId(), inventory1.getDescription());
                        //生成taskLog 日志
                        taskDto1.setMoveQty(taskDto1.getPlanQty());
                        taskDto1.setTaskStatus(BizStatus.PICK_ALL);
                        taskService.update(taskMapper.toEntity(taskDto1));
                        taskLogService.createTaskLogData(taskDto1, taskDto1.getPlanQty());
                        //存储拣货确认的库存数据
                        Task task = taskMapper.toEntity(taskDto1);
                        Inventory inventory11 = inventoryService.getInventory(inventory1.getItemKey(), inventory1.getArea(), task.getDstPoint(), task.getZzkw(), inventory1.getDept(), BizStatus.RECEIVING_UP,task.getDstStockCode());
                        invLogService.storeInventoryLog(BizStatus.PICK_DOWN, BizStatus.ADD, null, inventory11.getArea(), inventory11.getItemKey(), inventory11.getPoint(), inventory11.getPoint(), inventory11.getStock(), inventory11.getStock(), inventory11.getQuantity(), kcNum1,
                                null, null, BizStatus.PICK_DOWN, inventory11.getId(), inventory11.getId(), inventory11.getDescription());
                        inventory11.setQuantity(inventory11.getQuantity() + kcNum1);
                        inventory11.setQueuedQty(inventory11.getQueuedQty() + kcNum1);
                        inventoryService.update(inventory11);
                        inventoryRepository.delete(inventory1);
                    }
//                    PickDetail pickDetail1 = pickDetailRepository.queryByPickTicketIdItemId(pickTicketDto.getId(), taskDto1.getItem().getId());
                    PickDetail pickDetail1 = pickDetailRepository.getById(taskDto1.getPickDetail().getId());
                    if (Objects.isNull(pickDetail1)) {
                        throw new BadRequestException(HttpStatus.NOT_FOUND, taskDto1.getItem().getCode() + "未查到明细数据");
                    }
                    pickDetail1.setPickedQty(taskDto1.getPlanQty());
                    //回写 pickdetail 上的拣货数量
                    pickDetailService.update(pickDetail1);
                    //拣货数量
                    pickTicketDto.setPickedQuantity(pickTicketDto.getPickedQuantity() + taskDto1.getPlanQty());
                    pickTicketDto.setBhQty(pickTicketDto.getBhQty() + taskDto1.getPlanQty());
                    //发运数量
                    //pickTicketDto.setShippedQuantity(planQtySum);
                    if ((pickTicketDto.getOrderQuantity() - pickTicketDto.getPickedQuantity()) == 0) {
                        pickTicketDto.setStatus(BizStatus.PICK_ALL);
                    } else {
                        pickTicketDto.setStatus(BizStatus.PICKUP);
                    }
                    //备货日期（拣货写）
                    pickTicketDto.setStockingDate(new Timestamp(new Date().getTime()));
                    this.update(pickTicketMapper.toEntity(pickTicketDto));
                }
                break;
            case 4:
                //取消分配
                TaskQueryCriteria taskQueryCriteria1 = new TaskQueryCriteria();
                taskQueryCriteria1.setBillCode(pickTicketDto.getCode());
                List<TaskDto> taskDtos1 = taskService.queryAll(taskQueryCriteria1);
                if (taskDtos1.isEmpty()) {
                    throw new BadRequestException(HttpStatus.NOT_FOUND, pickTicketDto.getCode() + "单子,未查到分配的任务");
                }
                for (TaskDto taskDto1 : taskDtos1) {//所有分配的任务
                    List<Inventory> inventoriesData = inventoryService.queryInventory(pickTicketDto.getArea().getId(), taskDto1.getSrcPoint().getId(), taskDto1.getItemKey().getId());
                    if (inventoriesData.isEmpty()) {
                        throw new BadRequestException(HttpStatus.NOT_FOUND, taskDto1.getItem().getCode() + "未发现库存数据");
                    }
                    Inventory inventory1 = inventoriesData.get(0);
                    //已分配的还原回去
                    inventory1.setQueuedQty(inventory1.getQueuedQty() - taskDto1.getPlanQty());
                    inventoryService.update(inventory1);
                    //查明细 删除对应的task记录，pickdetail和pick上的占用数量相应扣减
//                    PickDetail pickDetail1 = pickDetailRepository.queryByPickTicketIdItemId(pickTicketDto.getId(), taskDto1.getItem().getId());
                    PickDetail pickDetail1 = pickDetailRepository.getById(taskDto1.getPickDetail().getId());
                    pickDetail1.setAllocatedQty(0d);
                    pickDetailService.update(pickDetail1);
                    pickTicketDto.setStatus(BizStatus.OPEN);
                    pickTicketDto.setAllocatedQuantity(0d);
                    this.update(pickTicketMapper.toEntity(pickTicketDto));
                    taskService.delete(taskDto1.getId());
                }
                break;
            case 7:
                //7现品票拣货
                //this.xppPickGoods(pickTicketButton);
                break;
            default:
                log.error("没有{}这个按钮的操作功能", pickConfirmNo);
                throw new BadRequestException(HttpStatus.NOT_FOUND, "操作出现问题");
        }
    }

    public void pickForTask(Long taskId, String stockCode, double pickQty, XppRecord xpp, String bhr) {
        Task task = taskService.getEntity(taskId);
        String barCode = xpp == null ? null : xpp.getEwm();
        double kcNum = pickQty;
        double fpQty = pickQty;
        if (pickQty == 0) {
            throw new BadRequestException(HttpStatus.NOT_FOUND, "拣货数量不能为0");
        }
        if (xpp == null || xpp.equals("")) {
            if ((task.getPlanQty() - task.getMoveQty() - pickQty) < 0) {
                throw new BadRequestException(HttpStatus.NOT_FOUND, "拣货数量大于分配数量");
            }
        }
        Boolean isCf= Boolean.FALSE;//是否超发
        double cfQty=0;
        if (pickQty > (task.getPlanQty() - task.getMoveQty())) {
            fpQty = task.getPlanQty() - task.getMoveQty();
            isCf=Boolean.TRUE;
            cfQty=pickQty-fpQty;
        }

        PickDetail pd = task.getPickDetail();
        PickTicket pt = pd.getPickTicket();
        Point zzkw=pd.getPoint();
        Area area=task.getArea();
        //大部品的库存不能进去
        Inventory srcInv = inventoryService.getInventory(task.getItemKey(),area,task.getSrcPoint(),zzkw,task.getDept(),BizStatus.PICK_DOWN,task.getDstStockCode());
        if (srcInv==null) {
            throw new BadRequestException(HttpStatus.NOT_FOUND, task.getItem().getCode() + "未发现库存数据");
        }
        //扣除后的数量
        double srcQty = srcInv.getQuantity();
        if (srcQty < pickQty) {
            throw new BadRequestException(HttpStatus.NOT_FOUND, "拣货数量大于库存数量");
        }
        //超发则需要判断库存是否还有足够未分配数量
        if(isCf){
            double wfp=srcInv.availableQty();
            if((int)wfp<(int)cfQty){
                throw new BadRequestException( "超发数"+cfQty+"大于可用库存数"+wfp);
            }
        }
        //库存扣除后还要  inventoryLog
        InventoryLog inventoryLog=invLogService.storeInventoryLog(BizStatus.PICK_DOWN, BizStatus.REDUCE, task.getBillCode(), srcInv.getArea(), srcInv.getItemKey(), srcInv.getPoint(),
                srcInv.getPoint(), zzkw, srcQty, pickQty, barCode, BizStatus.PICK_DOWN,
                task.getId(), srcInv.getId(), pd.getRemark());
        inventoryLog.setDstStockCode(srcInv.getStockCode());
        invLogService.update(inventoryLog);
        //生成taskLog 日志
        TaskLog taskLog = taskLogService.createTaskLog(task, pickQty, stockCode, barCode, bhr);
        if (xpp != null) {
            xpp.setCkTaskLog(taskLog);
            xpp.setBhr(SecurityUtils.getCurrentUsername());
            xpp.setBhDate(new Timestamp(new Date().getTime()));
            xppService.update(xpp);
        }
        task.setMoveQty(task.getMoveQty() + pickQty);
        if (task.getPlanQty() > task.getMoveQty()) {
            task.setTaskStatus(BizStatus.PICKUP);
        } else {
            task.setTaskStatus(BizStatus.PICK_ALL);
        }
        taskService.update(task);
        srcInv.reduce(pickQty);
        double srcQue=srcInv.getQueuedQty();
        srcInv.setQueuedQty(srcInv.getQueuedQty() - fpQty);
        if (srcInv.getQueuedQty().intValue()< 0) {
            srcInv.setQueuedQty(0d);
        }
        inventoryService.update(srcInv);
        //修改占用数，写入日志
        if(task.getTaskType()!=null&&!task.getTaskType().equals(BizStatus.XD_PICK)) {
            InventoryLog invLog = invLogService.storeInventoryLog(BizStatus.CHANGE_ZYS, BizStatus.REDUCE, task.getBillCode(), srcInv.getArea(), srcInv.getItemKey(), srcInv.getPoint(),
                    srcInv.getPoint(), srcInv.getZzkw(), srcQue, fpQty, null, BizStatus.PICK,
                    pd.getId(), srcInv.getId(), taskLog.getId() + "拣货确认");
            invLog.setDstQty(srcInv.getQueuedQty());
            invLog.setDstStockCode(srcInv.getStockCode());
            invLogService.update(invLog);
        }


        //生成备货库存，备货库存也不需要线边
       /** Inventory dstInv = inventoryService.getInventory(srcInv.getItemKey(), srcInv.getArea(), task.getDstPoint(), zzkw, srcInv.getDept(), BizStatus.PICK_DOWN,task.getDstStockCode());
        invLogService.storeInventoryLog(BizStatus.PICK_DOWN, BizStatus.ADD, pt.getCode(), dstInv.getArea(), dstInv.getItemKey(), dstInv.getPoint(), dstInv.getPoint(),
               zzkw, dstInv.getQuantity(), kcNum, barCode, BizStatus.PICK_DOWN, taskLog.getId(),
                dstInv.getId(),  pd.getRemark());
        dstInv.setQuantity(dstInv.getQuantity() + kcNum);
        inventoryService.update(dstInv); **/
        pd.setPickedQty(pd.getPickedQty() + pickQty);
        if(pd.getPickedQty()>0){
            pd.setStatus(BizStatus.PICKUP);
            if(pd.getPickedQty()>=pd.getOrderQty()){
                pd.setStatus(BizStatus.PICK_ALL);
            }
        }

        pickDetailRepository.save(pd);
        if(pt!=null) {
            //拣货数量
            pt.setPickedQuantity(pt.getPickedQuantity() + pickQty);
            pt.setBhQty(pt.getBhQty() + pickQty);
//        if ((pt.getOrderQuantity() - pt.getPickedQuantity()) <= 0) {
//            pt.setStatus(BizStatus.PICK_ALL);
//        } else {
//            pt.setStatus(BizStatus.PICKUP);
//        }
            if (pickDetailRepository.queryPickQty(pt.getId()).size() > 0) {
                pt.setStatus(BizStatus.PICKUP);
            } else {
                pt.setStatus(BizStatus.PICK_ALL);
            }
            this.update(pt);
        }
        if (xpp != null) {
            xpp.setStatus(BizStatus.PICK_ALL);
            xpp.setBhr(SecurityUtils.getCurrentUsername());
            xpp.setBhDate(new Timestamp(new Date().getTime()));
            xppRecordService.update(xpp);
        }
    }


    @Override
    public void xbjsVerify(Long[] ids) {
        for (Long id : ids) {
            List<PickDetail> pickDetails = pickDetailRepository.queryByPickTicketId(id);
            double shNum = 0d;
            double tlNum = 0d;
            if (!pickDetails.isEmpty()) {
                for (PickDetail pickDetail : pickDetails) {
                    shNum += pickDetail.getJsQty();
                    tlNum += pickDetail.getTlQty();
                }
            }
            PickTicket pickTicket = pickTicketRepository.getById(id);
            pickTicket.setTlQty(tlNum);
            pickTicket.setXbQty(shNum);
            pickTicket.setShipDate(new Timestamp(new Date().getTime()));
            this.update(pickTicket);
        }
    }

    @Override
    public List<TaskLog> queryTaskLogDataS(Long pickTicketId) {
        List<TaskLog> taskLogList = taskLogRepository.getTaskLogsByPtId(pickTicketId);
        return taskLogList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void pickingCancel(PickTicketButton pickTicketButton) {
        // 5拣货整单取消 6拣货批量取消
        int pickConfirmNo = pickTicketButton.getPickConfirmNo();
        PickTicket pickTicket = pickTicketRepository.getById(pickTicketButton.getPickTicketId());
        if (pickTicket.getShippedQuantity()>0) {
            throw new BadRequestException(HttpStatus.NOT_FOUND, "状态不正确");
        }
        //要取消的数量
        double pickedQuantityNum = 0d;
        if (pickConfirmNo == 5) { //拣货整单取消
            List<TaskLog> taskLogList = taskLogRepository.getTaskLogsCancelByPick(pickTicket.getId());
            if (taskLogList.isEmpty()) {
                throw new BadRequestException(HttpStatus.NOT_FOUND, "没有要取消的任务");
            }
            for (TaskLog taskLog : taskLogList) {
                pickedQuantityNum += taskLog.getMoveQty();
                this.backPick(taskLog.getId(), pickTicket.getArea());
            }
        } else if (pickConfirmNo == 6) {//拣货批量取消
            Long[] taskLogIdS = pickTicketButton.getTaskLogId();
            for (Long taskLogId : taskLogIdS) {
                TaskLog taskLog = taskLogRepository.getById(taskLogId);
                pickedQuantityNum += taskLog.getMoveQty();
                this.backPick(taskLogId, pickTicket.getArea());
            }
        } else {
            log.error("没有{}这个按钮的操作功能", pickConfirmNo);
            throw new BadRequestException(HttpStatus.NOT_FOUND, "操作出现问题");
        }
        pickTicket.setPickedQuantity(pickTicket.getPickedQuantity() - pickedQuantityNum);
        pickTicket.setBhQty(pickTicket.getBhQty() - pickedQuantityNum);
        pickTicket.setStatus(BizStatus.ALLOCATE);
        this.update(pickTicket);
    }

    @Override
    @Transactional
    public void shipmentRegistration(Long pickTicketId) {
        //其他出库直接发货登记，需记录具体日志轨迹(少了一步拣货的日志，出单状态下支持直接发货）
        //查询pickTicket 的数据
        PickTicketDto pickTicketDto = this.findById(pickTicketId);
        //判断
        if (!pickTicketDto.getStatus().equals(BizStatus.ALLOCATE)) {
            throw new BadRequestException(HttpStatus.NOT_FOUND, "只有已匹配状态的数据才能进行直接发货");
        }
        //主表总拣货数量
        double planQtySum = pickTicketDto.getOrderQuantity() - pickTicketDto.getPickedQuantity();
        double wcPlanQtySum = 0d;
        //查询对应的全部task数据
        TaskQueryCriteria taskQueryCriteria = new TaskQueryCriteria();
        taskQueryCriteria.setBillCode(pickTicketDto.getCode());
        List<TaskDto> taskDtos = taskService.queryAll(taskQueryCriteria);
        if (taskDtos.isEmpty()) {
            throw new BadRequestException(HttpStatus.NOT_FOUND, pickTicketDto.getCode() + "单子,未查到分配的任务");
        }
        Long[] taskLogIds = new Long[taskDtos.size()];
        int i = 0;
        for (TaskDto taskDto : taskDtos) {
            //要拣的数量
            double jhNum = taskDto.getPlanQty() - taskDto.getMoveQty();
            if (jhNum == 0) {
                continue;
            }
            //根据task扣除库存
            List<Inventory> inventoryList = inventoryService.queryInventory(pickTicketDto.getArea().getId(), taskDto.getSrcPoint().getId(), taskDto.getItemKey().getId());
            if (inventoryList.isEmpty()) {
                throw new BadRequestException(HttpStatus.NOT_FOUND, taskDto.getItem().getCode() + "未发现库存数据");
            }
            Inventory inventory = inventoryList.get(0);
            //库存扣除后的数量
            double subNum = inventory.getQuantity() - taskDto.getPlanQty();
            double kcNum = taskDto.getPlanQty();
            if (subNum < 0) {
                throw new BadRequestException(HttpStatus.NOT_FOUND, "拣货数量大于库存数量");
            }
            //库存扣除后还要  inventoryLog
            invLogService.storeInventoryLog(BizStatus.SHIPPING, BizStatus.REDUCE, null, inventory.getArea(), inventory.getItemKey(), inventory.getPoint(),
                    inventory.getPoint(), inventory.getStock(), inventory.getStock(), inventory.getQuantity(), kcNum, null, null, BizStatus.SHIPPING, inventory.getId(),
                    inventory.getId(), pickTicketDto.getDescription());
            //生成taskLog 日志
            TaskLog taskLog = taskLogService.createTaskLog(taskMapper.toEntity(taskDto), kcNum, null, null, "直接出库");
            taskLogIds[i++] = taskLog.getId();
            //拣货数量
            taskDto.setMoveQty(kcNum);
            taskDto.setTaskStatus(BizStatus.PICK_ALL);
            taskService.update(taskMapper.toEntity(taskDto));
            //库存的修改
            inventory.setQuantity(subNum);
            inventory.setQueuedQty(inventory.getQueuedQty() - taskDto.getPlanQty());
            if (subNum > 0) {//判断是否还有库存
                inventoryService.update(inventory);
            } else {
                inventoryRepository.delete(inventory);
            }
            PickDetail pickDetail = pickDetailRepository.getById(taskDto.getPickDetail().getId());
            if (Objects.isNull(pickDetail)) {
                throw new BadRequestException(HttpStatus.NOT_FOUND, taskDto.getItem().getCode() + "未查到明细数据");
            }
            pickDetail.setPickedQty(kcNum);
            wcPlanQtySum += kcNum;
        }
        if ((planQtySum - wcPlanQtySum) != 0) {
            throw new BadRequestException(HttpStatus.NOT_FOUND, "拣货失败");
        }
        pickTicketDto.setPickedQuantity(wcPlanQtySum);
        pickTicketDto.setBhQty(wcPlanQtySum);
        pickTicketDto.setStatus(BizStatus.PICK_ALL);
        this.update(pickTicketMapper.toEntity(pickTicketDto));
        //创建出库单维护
        PickOutButton pickOutButton = new PickOutButton();
        pickOutButton.setTaskLogIdS(taskLogIds);
        PickOut pickOutDto = pickOutService.createPickOutDto(pickOutButton);
        //发货
        pickOutService.confirmPickOutNotLog(pickOutDto.getId(), pickTicketId);
    }

    //刷新状态
    public  void refreshSatus(Long pick){

    }

    public void backPick(Long taskLogId, Area area) {
        //日志数据
        TaskLog taskLog = taskLogRepository.getById(taskLogId);
        if(taskLog.getShipQty()>0){
            throw new BadRequestException(HttpStatus.NOT_FOUND, "已发运，不能退");
        }
        double cancelNum = taskLog.getMoveQty();//取消的数量
        //task表数据
        Task task = taskLog.getTask();
        PickDetail pd = task.getPickDetail();
        Point zzkw = pd.getPoint();//pointService.findByCode("ZZKW",null,null,null,null);
        //源库存增加，目标减少
        Inventory srcInv = inventoryService.getInventory(taskLog.getItemKey(), area, taskLog.getSrcPoint(), zzkw, taskLog.getDept(), BizStatus.PICK_CANCEL,task.getDstStockCode());
        //添加物料
        srcInv.setQuantity(srcInv.getQuantity() + cancelNum);
        //修改占用数，写入日志
        invLogService.storeInventoryLog(BizStatus.CHANGE_ZYS, BizStatus.ADD, task.getBillCode(), srcInv.getArea(), srcInv.getItemKey(), srcInv.getPoint(),
                srcInv.getPoint(), srcInv.getZzkw(),srcInv.getQueuedQty(), cancelNum, null, BizStatus.PICK,
                pd.getId(), srcInv.getId(), taskLogId+"拣货退回");
        srcInv.setQueuedQty(srcInv.getQueuedQty() + cancelNum);
        inventoryService.update(srcInv);
        //生成日志
        invLogService.storeInventoryLog(BizStatus.PICK_CANCEL, BizStatus.ADD, task.getBillCode(), srcInv.getArea(), srcInv.getItemKey(), srcInv.getPoint(),
                srcInv.getPoint(), zzkw, (srcInv.getQuantity() - cancelNum), cancelNum, taskLog.getSrcStockCode(),
                 BizStatus.PICK_CANCEL, taskLog.getId(), srcInv.getId(), srcInv.getDescription());
        //task表的修改
        task.setMoveQty(task.getMoveQty() - cancelNum);
        if (task.getMoveQty() == 0) {
            task.setTaskStatus(BizStatus.OPEN);
        } else {
            task.setTaskStatus(BizStatus.PICK);
        }
        pd.setPickedQty(pd.getPickedQty() - cancelNum);
        pickDetailService.update(pd);
        //扣库存
        Inventory dstInv = inventoryService.getInventory(taskLog.getItemKey(), area, taskLog.getDstPoint(), zzkw, taskLog.getDept(), BizStatus.PICK_CANCEL,null);
        if (dstInv==null) {
            throw new BadRequestException(HttpStatus.NOT_FOUND, taskLog.getItem().getCode() + "未发现库存数据");
        }
        if (dstInv.getQuantity() < cancelNum) {
            throw new BadRequestException(HttpStatus.NOT_FOUND, taskLog.getItem().getCode() + "库存不足单子出现问题");
        }
        invLogService.storeInventoryLog(BizStatus.PICK_CANCEL, BizStatus.REDUCE, task.getBillCode(), dstInv.getArea(), dstInv.getItemKey(), dstInv.getPoint(), dstInv.getPoint(), zzkw, dstInv.getQuantity(), cancelNum,
                 taskLog.getSrcStockCode(), BizStatus.PICK_CANCEL, taskLog.getId(), dstInv.getId(), dstInv.getDescription());
        dstInv.setQuantity(dstInv.getQuantity() - cancelNum);
        if (dstInv.getQuantity() > 0) {
            inventoryService.update(dstInv);
        }
        taskService.update(task);
        if (taskLog.getSrcStockCode() != null) {
            XppRecord xpp = xppRecordRepository.findByCode(taskLog.getSrcStockCode());
            if (xpp != null) {
                xpp.setCkTaskLog(null);
                xpp.setBhDate(null);
                xpp.setBhr(null);
                xpp.setStatus(BizStatus.PUTAWAY);
                xppService.update(xpp);
            }
        }
        //删除task日志数据
        taskLogRepository.delete(taskLog);
    }

    public void backPickOut(Long taskLogId, Area area) {
        //日志数据
        TaskLog taskLog = taskLogRepository.getById(taskLogId);
        double cancelNum = taskLog.getShipQty();//发货取消，从出库到分配
        //task表数据
        Task task = taskLog.getTask();
        PickDetail pd = task.getPickDetail();
        Point zzkw = pd.getPoint();
        //源库存增加
        Inventory srcInv = inventoryService.getInventory(taskLog.getItemKey(), area, taskLog.getDstPoint(), zzkw, taskLog.getDept(), BizStatus.SHIP_CANCEL,null);
        srcInv.setQuantity(srcInv.getQuantity() + cancelNum);
        srcInv.setQueuedQty(srcInv.getQueuedQty() + cancelNum);
        inventoryService.update(srcInv);
        //生成日志
        invLogService.storeInventoryLog(BizStatus.SHIP_CANCEL, BizStatus.ADD, task.getBillCode(), srcInv.getArea(), srcInv.getItemKey(), srcInv.getPoint(),
                srcInv.getPoint(), zzkw, (srcInv.getQuantity() - cancelNum), cancelNum, taskLog.getSrcStockCode(),
                BizStatus.SHIP_CANCEL, taskLog.getId(), srcInv.getId(), "出库退回");
        pd.setPickedQty(pd.getPickedQty() - cancelNum);
        pickDetailService.update(pd);
        PickTicket pickTicket=pd.getPickTicket();
        pickTicket.setStatus(BizStatus.PICK_ALL);
        pickTicket.setShippedQuantity(pickTicket.getShippedQuantity()-cancelNum);
        taskService.update(task);
        if (taskLog.getSrcStockCode() != null) {
            XppRecord xpp = xppRecordRepository.findByCode(taskLog.getSrcStockCode());
            if (xpp != null) {
                xpp.setCkTaskLog(null);
                xpp.setBhDate(null);
                xpp.setBhr(null);
//                xpp.setFhr(null);
//                xpp.setFhDate(null);
                xpp.setStatus(BizStatus.PICK_ALL);
                xppService.update(xpp);
            }
        }
        taskLog.setShipQty(0d);
        taskLogService.update(taskLog);
    }

    public List<RPPickList> queryPickList(IScanPut t) {
        String sql = "SELECT pt.code ,pt.gc_code,ck.code ck_area, pt.id pickTicketId,pt.`status`,DATE_FORMAT(pt.order_date, '%Y-%m-%d') orderDate,ck.working_station gw,pt.order_quantity dds,pt.picked_quantity bhs\n" +
                " FROM `data_pick_ticket` pt\n" +
                "left join base_area ck on ck.id=pt.area\n" +
                "where 1=1  and pt.status in ('ALLOCATE','PICKUP') " +
                " and pt.allocated_quantity>0 and (pt.code like 'B%' or pt.code like 'ZS%')" ;
                //" and pt.id in (select d.pick_ticket_id from data_Pick_Detail d where d.picked_Qty<allocated_Qty)";
        if (t.getScanCode() != null && !t.getScanCode().equals("")) {
            sql += " and pt.code ='" + t.getScanCode() + "'";
        }
        Long user_id=SecurityUtils.getCurrentUserId();
        List<Job> jobs=jobRepository.jobAreaCodes(user_id);
        if(jobs.size()>0){
            sql += " and ck.code ='" + jobs.get(0).getAreaCode() + "'";
        }
        sql += " ORDER BY pt.code desc";
        List ts = entityManager.createNativeQuery(sql)
                .unwrap(SQLQuery.class)
                .setResultTransformer(
                        AliasToEntityMapResultTransformer.INSTANCE
                )
                .list();
        List<RPPickList> l = JSON.parseArray(JSON.toJSONString(ts), RPPickList.class);
        return l;
    }
}