package com.wms.controller;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wms.annotation.MyLog;
import com.wms.constants.enums.*;
import com.wms.entity.app.*;
import com.wms.entity.app.dto.PageDto;
import com.wms.entity.app.dto.StockOfGoodsDto;
import com.wms.entity.app.dto.extend.StockDetailInfo;
import com.wms.entity.app.request.*;
import com.wms.entity.app.vo.BoxPrintData;
import com.wms.entity.app.vo.StandPickFinishVo;
import com.wms.entity.app.vo.StandPickVo;
import com.wms.entity.app.vo.TaskVO;
import com.wms.entity.app.wcs.*;
import com.wms.entity.table.*;
import com.wms.service.*;
import com.wms.service.business.IValidateService;
import com.wms.service.business.IWcsService;
import com.wms.service.business.IWmsTaskService;
import com.wms.service.business.IWorkService;
import com.wms.utils.HttpUtils;
import com.wms.utils.StringUtils;
import com.wms.utils.WmsUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.wms.config.InitLocalConfig.configMap;
import static com.wms.constants.WmsConstants.MYSQL_JSON_CI;
import static com.wms.utils.StringUtils.convertJsonString;
import static com.wms.utils.WmsUtils.generateId;

/**
 * WMS任务控制类
 *
 * @author 梁州
 * &#064;date  2023/2/14
 */
@Controller
@CrossOrigin
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@RequestMapping(value = "/wms/task")
public class TaskController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * 任务服务
     */
    private final TaskService taskService;
    /**
     * 库存服务
     */
    private final StockService stockService;
    /**
     * 库位服务
     */
    private final LocationService locationService;
    /**
     * 任务记录服务
     */
    private final TaskRecordService taskRecordService;
    /**
     * 载具服务
     */
    private final VehicleService vehicleService;
    /**
     * 拣选任务服务
     */
    private final PickTaskService pickTaskService;
    /**
     * 请求头部信息
     */
    private final HttpServletRequest servletRequest;
    /**
     * WMS任务服务
     */
    private final IWmsTaskService wmsTaskService;
    /**
     * 验证服务
     */
    private final IValidateService validateService;
    /**
     * 站台服务
     */
    private final StandService standService;
    /**
     * 工作流服务
     */
    private final WorkFlowService workFlowService;
    /**
     * ETag库位服务
     */
    private final ETagLocationService etagLocationService;
    /**
     * 电子标签配置服务
     */
    private final ELocationConfigService eLocationConfigService;
    /**
     * 物料服务
     */
    private final GoodsService goodsService;
    /**
     * 流转中物料箱号数据
     */
    private final OutsideVehiclesService outsideVehiclesService;
    /**
     * 拣选任务记录服务
     */
    private final PickTaskRecordService pickTaskRecordService;
    /**
     * DBS服务
     */
    private final KateDBSService kateDBSService;
    /**
     * 上一次标签配置的服务
     */
    private final ELocationConfigLastService eLocationConfigLastService;
    /**
     * 工作站配置服务
     */
    private final WorkStationConfigService workStationConfigService;
    /**
     * 站台要料服务
     */
    private final GoodsToStationService goodsToStationService;
    /**
     * 非计划领料服务
     */
    private final NoPlanRecordService noPlanRecordService;
    /**
     * 库存更新服务
     */
    private final IStockUpdateRecordService stockUpdateRecordService;
    /**
     * 看板服务
     */
    private final KanbanService kanbanService;
    /**
     * 日志服务
     */
    private final LogService logService;
    /**
     * Wcs服务
     */
    private final IWcsService wcsService;
    /**
     * 工作服务
     */
    private final IWorkService workService;

    /**
     * 接收入库任务请求
     *
     * @param taskInRequest 入库任务
     * @return 结果
     */
    @PostMapping("/requestIn")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    @MyLog(logTitle = "入库请求", logMethod = "requestIn")
    public String receiveTaskInRequest(@RequestBody TaskInRequest taskInRequest) {
        logger.info("接收到入库请求：{}，ip地址：{}", convertJsonString(taskInRequest), HttpUtils.getIpAddr(servletRequest));
        // 创建响应信息
        ResponseEntity response = new ResponseEntity();
        try {
            // 验证入库请求
            String validationInfo = validateService.validateTaskInRequest(taskInRequest);
            if (!Objects.equals(validationInfo, TaskInValidationEnum.OK.getErrorMessage())) {
                logger.error("入库请求验证错误！{}", validationInfo);
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("入库请求验证错误！" + validationInfo);
                return convertJsonString(response);
            }
            // 查找当前箱子是否有其他等待入库的箱子
            Task sameVehicleTempTask = taskService.getOne(new LambdaQueryWrapper<Task>()
                    .eq(Task::getVehicleId, taskInRequest.getVehicleId())
                    .eq(Task::getTaskStatus, WmsTaskStatus.TEMP.getCode())
                    .eq(Task::getTaskType, TaskType.IN.getCode())
                    .last("limit 1"));
            // 生成入库任务
            String saveTaskResult;
            if (sameVehicleTempTask != null) {// 有相同的箱子任务
                if (taskInRequest.getGoodsList() == null || taskInRequest.getGoodsList().isEmpty()) {// 空托入库
                    saveTaskResult = "不允许重复入空箱";
                } else {// 带料入库
                    // 判断当前的料能否放入这个箱子里面
                    saveTaskResult = wmsTaskService.genGoodsInTask(taskInRequest, sameVehicleTempTask);
                }
            } else {// 没有这个箱子的任务
                if (taskInRequest.getGoodsList() == null || taskInRequest.getGoodsList().isEmpty()) {// 空托入库
                    saveTaskResult = wmsTaskService.genEmptyInTask(taskInRequest);
                } else {// 带料入库
                    saveTaskResult = wmsTaskService.genGoodsInTask(taskInRequest, null);
                }
            }

            if (!saveTaskResult.equals("")) {
                // 返回失败
                logger.error(saveTaskResult);
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage(saveTaskResult);
                return convertJsonString(response);
            }

            logger.info("接收入库请求成功！");
            response.setCode(ResponseCode.OK.getCode());
            response.setMessage("接收入库请求成功！");
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("发生异常：{}", e.getMessage());
            // 返回其他异常
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("发生意料之外的错误");
            return convertJsonString(response);
        }
    }

    /**
     * 接收出库任务请求
     *
     * @param taskOutRequest 出库任务
     * @return 结果
     */
    @PostMapping("/requestOut")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    @MyLog(logTitle = "出库请求", logMethod = "requestOut")
    public String receiveTaskOutRequest(@RequestBody TaskOutRequest taskOutRequest) {
        logger.info("接收到出库请求：{}，ip地址：{}", convertJsonString(taskOutRequest), HttpUtils.getIpAddr(servletRequest));
        // 创建响应信息
        ResponseEntity response = new ResponseEntity();
        try {
            // 验证出库请求
            String validationInfo = validateService.validateTaskOutRequest(taskOutRequest);
            if (!Objects.equals(validationInfo, TaskInValidationEnum.OK.getErrorMessage())) {
                logger.error("出库请求验证错误！{}", validationInfo);
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("出库请求验证错误：" + validationInfo);
                return convertJsonString(response);
            }
            // 没有物料，单纯载具或者库位出库
            String genResult;
            if (StringUtils.isEmpty(taskOutRequest.getGoodsId())) {
                genResult = wmsTaskService.genVehicleLocationOutTask(taskOutRequest);
            } else {
                genResult = wmsTaskService.genGoodsOutTask(taskOutRequest);
            }
            if (!genResult.equals("")) {
                logger.error("出库错误！{}", genResult);
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("出库错误：" + genResult);
                return convertJsonString(response);
            }

            logger.info("处理出库请求成功！");
            response.setCode(ResponseCode.OK.getCode());
            response.setMessage("处理出库请求成功！");
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("发生异常：{}", convertJsonString(e));
            // 返回其他异常
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("发生意料之外的错误");
            return convertJsonString(response);
        }
    }

    /**
     * 接收任务反馈
     *
     * @param wcsTaskResultRequest wcs任务反馈请求
     * @return 结果
     */
    @PostMapping("/sendTaskResult")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    @MyLog(logTitle = "Wcs任务反馈", logMethod = "sendTaskResult")
    public String receiveTaskResult(@RequestBody WcsTaskResultRequest wcsTaskResultRequest) {
        logger.info("接收到任务反馈：{}，ip地址：{}", convertJsonString(wcsTaskResultRequest), HttpUtils.getIpAddr(servletRequest));
        // 创建响应信息
        ResponseEntity response = new ResponseEntity();
        try {
            String validateInfo = validateService.validateTaskResult(wcsTaskResultRequest);
            if (!Objects.equals(validateInfo, TaskResultValidationEnum.OK.getErrorMessage())) {
                logger.error("任务反馈请求验证失败：{}", validateInfo);
                // 返回其他异常
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("任务反馈请求验证失败：" + validateInfo);
                return convertJsonString(response);
            }
            // 解析任务号
            List<Task> feedBackTasks = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getTaskGroup, wcsTaskResultRequest.getTaskId()));
            // 任务状态
            int taskType = feedBackTasks.get(0).getTaskType();
            // 任务状态
            int taskStatus = wcsTaskResultRequest.getTaskStatus();
            // 判断任务状态
            if (taskStatus == WcsTaskStatus.FINISH.getCode()) {// 任务完成
                // 入库任务完成
                if (taskType == TaskType.IN.getCode()) {
                    // 对所有任务组里面的入库任务进行处理
                    for (Task inTask : feedBackTasks) {
                        if (!Objects.equals(inTask.getTaskType(), TaskType.IN.getCode())) {
                            // 非入库任务跳过
                            continue;
                        }
                        // 当前载具是否有移库任务
                        boolean haveMoveTask = taskService.exists(new LambdaQueryWrapper<Task>()
                                .eq(Task::getVehicleId, inTask.getVehicleId())
                                .eq(Task::getTaskType, TaskType.MOVE.getCode()));
                        // 如果是入库
                        if (inTask.getTaskId().startsWith("RK")) {
                            // 添加库存
                            if (inTask.getGoodsRelated() != null && StringUtils.isNotEmpty(inTask.getGoodsRelated().getGoodsId())) {
                                // 查询这个物料有没有库存
                                Stock existStock = stockService.getOne(new LambdaQueryWrapper<Stock>()
                                        .apply("goods_related ->> '$.goodsId' = {0}" + MYSQL_JSON_CI, inTask.getGoodsRelated().getGoodsId())
                                        .eq(Stock::getVehicleId, inTask.getVehicleId())
                                        .last("limit 1"));
                                if (existStock != null) {
                                    Stock originStock = BeanUtil.copyProperties(existStock, Stock.class);
                                    BigDecimal quantityBefore = originStock.getGoodsRelated().getRemainNum();
                                    // 已有库存，直接更新数量
                                    existStock.setLocationId(inTask.getDestination());
                                    existStock.getGoodsRelated().setRemainNum(existStock.getGoodsRelated().getRemainNum().add(inTask.getGoodsRelated().getOpNum()));
                                    existStock.getGoodsRelated().setTotalNum(existStock.getGoodsRelated().getTotalNum().add(inTask.getGoodsRelated().getOpNum()));
                                    stockService.update(existStock, new LambdaUpdateWrapper<Stock>().eq(Stock::getStockId, existStock.getStockId()));
                                    stockUpdateRecordService.addStockUpdateRecord(originStock, existStock, StockUpdateReasonEnum.UPDATE_IN.getReason(), inTask.getUserName(), quantityBefore);
                                } else {
                                    Stock newStock = new Stock();
                                    newStock.setStockId(generateId("ST_"));
                                    newStock.setVehicleId(inTask.getVehicleId());
                                    newStock.setLocationId(inTask.getDestination());
                                    newStock.setNoUseDays(0);
                                    newStock.setIsInventory(0);
                                    newStock.setCreateTime(LocalDateTime.now());
                                    newStock.setWeight(inTask.getWeight());
                                    StockDetailInfo detailInfo = new StockDetailInfo();
                                    detailInfo.setGoodsId(inTask.getGoodsRelated().getGoodsId());
                                    detailInfo.setGoodsName(inTask.getGoodsRelated().getGoodsName());
                                    detailInfo.setGoodsStatus(GoodsStatus.OK.getCode());
                                    detailInfo.setRemainNum(inTask.getGoodsRelated().getOpNum());
                                    detailInfo.setTotalNum(inTask.getGoodsRelated().getOpNum());
                                    newStock.setGoodsRelated(detailInfo);
                                    stockService.save(newStock);
                                    stockUpdateRecordService.addStockUpdateRecord(null, newStock, StockUpdateReasonEnum.ADD_IN.getReason(), inTask.getUserName(), BigDecimal.ZERO);
                                }
                                // 消除看板
                                Goods goods = goodsService.getOne(new LambdaQueryWrapper<Goods>().eq(Goods::getGoodsId, inTask.getGoodsRelated().getGoodsId()).last("limit 1"));
                                if (goods != null && goods.getFeedingType().equals("PULL")) {
                                    if (goods.getKanbanList() != null && !goods.getKanbanList().isEmpty()) {
                                        BigDecimal kanbanQuantity = inTask.getGoodsRelated().getOpNum().divide(goods.getQuantityPerKanban(), 0, RoundingMode.FLOOR);
                                        // 查这个料的看板需求
                                        List<Kanban> waitForUpdateKanban = new ArrayList<>();
                                        List<Kanban> kanbanList = kanbanService.list(new LambdaQueryWrapper<Kanban>()
                                                .eq(Kanban::getGoodsId, goods.getGoodsId())
                                                .eq(Kanban::getKanbanStatus, 0)
                                                .orderByAsc(Kanban::getLastRequestTime));
                                        for (Kanban kanban : kanbanList) {
                                            if (kanbanQuantity.compareTo(BigDecimal.ZERO) <= 0) {
                                                break;
                                            }
                                            kanban.setKanbanStatus(1);
                                            kanban.setLastPullTime(LocalDateTime.now());
                                            waitForUpdateKanban.add(kanban);
                                            kanbanQuantity = kanbanQuantity.subtract(BigDecimal.ONE);
                                        }
                                        // 更新看板信息
                                        kanbanService.updateBatchById(waitForUpdateKanban);
                                    }
                                }
                            }
                        }
                        // 更新库存状态
                        List<Stock> backStocks = stockService.list(new LambdaQueryWrapper<Stock>()
                                .eq(Stock::getVehicleId, inTask.getVehicleId()));
                        for (Stock stock : backStocks) {
                            if (stock.getGoodsRelated().getRemainNum().compareTo(BigDecimal.ZERO) == 0) {
                                // 库存数量为0时要删除当前库存
                                stockService.removeById(stock.getStockId());
                            } else {
                                if (haveMoveTask) {
                                    // 后续有移库
                                    stock.setStockStatus(StockStatus.MOVE.getCode());
                                } else {
                                    // 后续没有移库
                                    stock.setStockStatus(StockStatus.OK.getCode());
                                }
                                stock.setLocationId(inTask.getDestination());
                                stock.setLastUpdateTime(LocalDateTime.now());
                                stock.setLastUpdateUser(inTask.getUserName());
                                stockService.update(stock, new LambdaUpdateWrapper<Stock>().eq(Stock::getStockId, stock.getStockId()));
                            }
                        }
                        // 当前载具
                        Vehicle currentVehicle = vehicleService.getOne(new LambdaQueryWrapper<Vehicle>().eq(Vehicle::getVehicleId, inTask.getVehicleId()).last("limit 1"));
                        if (currentVehicle == null) {
                            // 添加载具
                            Vehicle newVehicle = new Vehicle();
                            newVehicle.setVehicleId(inTask.getVehicleId());
                            newVehicle.setVehicleType("");
                            newVehicle.setVehicleStatus(VehicleStatus.ON.getCode());
                            newVehicle.setCurrentLocation(inTask.getDestination());
                            if (haveMoveTask) {
                                newVehicle.setVehicleStatus(VehicleStatus.MOVE.getCode());
                            } else {
                                newVehicle.setVehicleStatus(VehicleStatus.ON.getCode());
                            }
                            boolean haveStocks = stockService.exists(new LambdaQueryWrapper<Stock>().eq(Stock::getVehicleId, inTask.getVehicleId()));
                            if (haveStocks) {
                                newVehicle.setIsEmpty(0);
                            } else {
                                newVehicle.setIsEmpty(1);
                            }
                            newVehicle.setLastInTime(LocalDateTime.now());
                            vehicleService.save(newVehicle);
                        } else {
                            // 更新载具
                            currentVehicle.setCurrentLocation(inTask.getDestination());
                            if (haveMoveTask) {
                                currentVehicle.setVehicleStatus(VehicleStatus.MOVE.getCode());
                            } else {
                                currentVehicle.setVehicleStatus(VehicleStatus.ON.getCode());
                            }
                            boolean haveStocks = stockService.exists(new LambdaQueryWrapper<Stock>().eq(Stock::getVehicleId, inTask.getVehicleId()));
                            if (haveStocks) {
                                currentVehicle.setIsEmpty(0);
                            } else {
                                currentVehicle.setIsEmpty(1);
                            }
                            currentVehicle.setLastInTime(LocalDateTime.now());
                            vehicleService.update(currentVehicle, new LambdaUpdateWrapper<Vehicle>().eq(Vehicle::getVehicleId, currentVehicle.getVehicleId()));
                        }
                        // 添加任务记录
                        inTask.setTaskStatus(WmsTaskStatus.FINISH.getCode());
                        inTask.setFinishTime(LocalDateTime.now());
                        taskRecordService.save(BeanUtil.copyProperties(inTask, TaskRecord.class));
                        // 删除移库任务
                        taskService.remove(new LambdaQueryWrapper<Task>().eq(Task::getTaskId, inTask.getTaskId()));
                        // 移除当前料箱所有的拣选任务
                        pickTaskService.remove(new LambdaQueryWrapper<PickTask>().eq(PickTask::getVehicleId, inTask.getVehicleId()));
                        // 移除当前料箱所有的outsideVehicles
                        outsideVehiclesService.remove(new LambdaQueryWrapper<OutsideVehicles>().eq(OutsideVehicles::getVehicleId, inTask.getVehicleId()));
                    }
                }
                // 出库任务
                if (taskType == TaskType.OUT.getCode()) {
                    // 对所有任务组里面的出库任务进行处理
                    for (Task outTask : feedBackTasks) {
                        if (!Objects.equals(outTask.getTaskType(), TaskType.OUT.getCode())) {
                            // 非出库任务跳过
                            continue;
                        }
                        if (outTask.getIsPicking() == 1) {
                            // 当前载具设置为出库中状态
                            vehicleService.update(new LambdaUpdateWrapper<Vehicle>()
                                    .set(Vehicle::getVehicleStatus, VehicleStatus.OUT.getCode())
                                    .eq(Vehicle::getVehicleId, outTask.getVehicleId())
                                    .ne(Vehicle::getVehicleStatus, VehicleStatus.OUT.getCode()));
                            if (StringUtils.isNotEmpty(outTask.getPickStand())) {
                                // 当前载具上所有库存状态设置为拣选
                                stockService.update(new LambdaUpdateWrapper<Stock>()
                                        .set(Stock::getStockStatus, StockStatus.PICKING.getCode())
                                        .eq(Stock::getVehicleId, outTask.getVehicleId())
                                        .ne(Stock::getStockStatus, StockStatus.PICKING.getCode()));
                                // 将该载具对应的拣选任务设置为可发送状态
                                pickTaskService.update(new LambdaUpdateWrapper<PickTask>()
                                        .set(PickTask::getPickStatus, PickTaskStatusEnum.NEW.getCode())
                                        .eq(PickTask::getVehicleId, outTask.getVehicleId())
                                        .eq(PickTask::getPickStatus, PickTaskStatusEnum.TEMP.getCode()));
                            }
                        } else {// 代表整出
                            // 删除当前载具上所有库存
                            List<Stock> removeStocks = stockService.list(new LambdaQueryWrapper<Stock>().eq(Stock::getVehicleId, outTask.getVehicleId()));
                            for (Stock stock : removeStocks) {
                                stockUpdateRecordService.addStockUpdateRecord(stock, null, StockUpdateReasonEnum.FULL_OUT.getReason(), outTask.getUserName(), stock.getGoodsRelated().getRemainNum());
                            }
                            stockService.remove(new LambdaQueryWrapper<Stock>().eq(Stock::getVehicleId, outTask.getVehicleId()));
                            // 删除载具
                            vehicleService.remove(new LambdaQueryWrapper<Vehicle>().eq(Vehicle::getVehicleId, outTask.getVehicleId()));
                            // 删除当前载具的所有拣选任务
                            pickTaskService.remove(new LambdaQueryWrapper<PickTask>().eq(PickTask::getVehicleId, outTask.getVehicleId()));
                        }
                        // 添加任务记录
                        outTask.setTaskStatus(WmsTaskStatus.FINISH.getCode());
                        outTask.setFinishTime(LocalDateTime.now());
                        taskRecordService.save(BeanUtil.copyProperties(outTask, TaskRecord.class));
                        // 删除出库任务
                        taskService.remove(new LambdaQueryWrapper<Task>().eq(Task::getTaskId, outTask.getTaskId()));
                        // 释放原来的库位
                        locationService.update(new LambdaUpdateWrapper<Location>()
                                .set(Location::getLocationStatus, LocationStatus.EMPTY.getCode())
                                .set(Location::getVehicleId, "")
                                .eq(Location::getLocationId, outTask.getOrigin()));
                    }
                }
                // 移库任务完成
                if (taskType == TaskType.MOVE.getCode()) {
                    // 对所有任务组里面的移库任务进行处理
                    for (Task moveTask : feedBackTasks) {
                        if (!Objects.equals(moveTask.getTaskType(), TaskType.MOVE.getCode())) {
                            // 非移库任务跳过
                            continue;
                        }
                        // 更新库存
                        LambdaUpdateWrapper<Stock> lambdaUpdateWrapperOfStock = new LambdaUpdateWrapper<Stock>()
                                .set(Stock::getLocationId, moveTask.getDestination())
                                .set(Stock::getStockStatus, StockStatus.OK.getCode())
                                .set(Stock::getLastUpdateTime, LocalDateTime.now())
                                .set(Stock::getLastUpdateUser, moveTask.getUserName())
                                .eq(Stock::getVehicleId, moveTask.getVehicleId())
                                .eq(Stock::getStockStatus, StockStatus.MOVE.getCode());
                        stockService.update(lambdaUpdateWrapperOfStock);
                        // 更新载具
                        LambdaUpdateWrapper<Vehicle> lambdaUpdateWrapperOfVehicle = new LambdaUpdateWrapper<Vehicle>()
                                .set(Vehicle::getVehicleStatus, VehicleStatus.ON.getCode())
                                .set(Vehicle::getCurrentLocation, moveTask.getDestination())
                                .eq(Vehicle::getVehicleId, moveTask.getVehicleId())
                                .eq(Vehicle::getVehicleStatus, VehicleStatus.MOVE.getCode());
                        vehicleService.update(lambdaUpdateWrapperOfVehicle);
                        // 释放原来的库位
                        LambdaUpdateWrapper<Location> lambdaUpdateWrapperOfLocation = new LambdaUpdateWrapper<Location>()
                                .set(Location::getLocationStatus, LocationStatus.EMPTY.getCode())
                                .set(Location::getVehicleId, "")
                                .eq(Location::getLocationId, moveTask.getOrigin())
                                .eq(Location::getLocationStatus, LocationStatus.OCCUPY.getCode());
                        locationService.update(lambdaUpdateWrapperOfLocation);
                        // 添加任务记录
                        moveTask.setTaskStatus(WmsTaskStatus.FINISH.getCode());
                        moveTask.setFinishTime(LocalDateTime.now());
                        taskRecordService.save(BeanUtil.copyProperties(moveTask, TaskRecord.class));
                        // 删除移库任务
                        taskService.remove(new LambdaQueryWrapper<Task>().eq(Task::getTaskId, moveTask.getTaskId()));
                    }
                }
            } else if (taskStatus == WcsTaskStatus.RUN.getCode()) {// 任务开始运行
                // 更新任务状态为正在运行
                for (Task task : feedBackTasks) {
                    task.setTaskStatus(WmsTaskStatus.RUN.getCode());
                }
                taskService.updateBatchById(feedBackTasks);
            }

            // 返回成功
            logger.info("处理任务反馈成功");
            response.setCode(ResponseCode.OK.getCode());
            response.setMessage("处理任务反馈成功");
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("发生异常：{}", convertJsonString(e));
            // 返回其他异常
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("任务反馈发生异常");
            return convertJsonString(response);
        }
    }

    /**
     * Wcs请求载具入库
     *
     * @param wcsVehicleInRequest 载具入库请求
     * @return 结果
     */
    @PostMapping("/wcsVehicleIn")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    @MyLog(logTitle = "Wcs请求载具入库", logMethod = "wcsVehicleIn")
    public String wcsVehicleInRequest(@RequestBody WcsVehicleInRequest wcsVehicleInRequest) {
        logger.info("接收到Wcs请求载具入库：{}，ip地址：{}", convertJsonString(wcsVehicleInRequest), HttpUtils.getIpAddr(servletRequest));
        // 创建响应信息
        ResponseEntity response = new ResponseEntity();
        try {
            // 验证入库请求
            String validationInfo = validateService.validateVehicleRequest(wcsVehicleInRequest);
            if (!Objects.equals(validationInfo, "")) {
                logger.error("请求载具入库发生错误：{}", validationInfo);
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("请求载具入库发生错误：" + validationInfo);
                return convertJsonString(response);
            }
            // 请求可用库位
            String nextLocationId = "";
            for (int i = 0; i < locationService.count(new LambdaQueryWrapper<Location>().eq(Location::getLocationStatus, LocationStatus.EMPTY.getCode())); i++) {
                Map<String, String> resultMap = locationService.getOneLocation("", "");
                if (resultMap.isEmpty() || !resultMap.containsKey("nextLocationId")) {
                    logger.error("暂无可用库位");
                    response.setCode(ResponseCode.ERROR.getCode());
                    response.setMessage("暂无可用库位！");
                    return convertJsonString(response);
                } else {
                    Location nextLocation = locationService.getOne(new LambdaQueryWrapper<Location>().eq(Location::getLocationId, resultMap.get("nextLocationId")).last("limit 1"));
                    LambdaUpdateWrapper<Location> updateLocationWrapper = new LambdaUpdateWrapper<Location>()
                            .set(Location::getLocationStatus, LocationStatus.OCCUPY.getCode())
                            .set(Location::getVehicleId, wcsVehicleInRequest.getVehicleNo())
                            .eq(Location::getLocationId, nextLocation.getLocationId())
                            .eq(Location::getLocationStatus, LocationStatus.EMPTY.getCode());
                    if (locationService.update(updateLocationWrapper)) {
                        nextLocationId = resultMap.get("nextLocationId");
                        break;
                    }
                }
            }
            if (Objects.equals(nextLocationId, "")) {
                logger.error("暂无可用库位");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("暂无可用库位！");
                return convertJsonString(response);
            }
            // 找到库位，更新任务
            LambdaUpdateWrapper<Task> lambdaUpdateWrapperOfTask = new LambdaUpdateWrapper<Task>()
                    .set(Task::getDestination, nextLocationId)
                    .set(Task::getTaskStatus, WmsTaskStatus.NEW.getCode())
                    .eq(Task::getVehicleId, wcsVehicleInRequest.getVehicleNo())
                    .eq(Task::getTaskType, TaskType.IN.getCode())
                    .eq(Task::getTaskStatus, WmsTaskStatus.TEMP.getCode());
            if (!taskService.update(lambdaUpdateWrapperOfTask)) {
                // 回退库位锁定
                locationService.update(new LambdaUpdateWrapper<Location>()
                        .set(Location::getLocationStatus, LocationStatus.EMPTY.getCode())
                        .set(Location::getVehicleId, "")
                        .eq(Location::getLocationId, nextLocationId)
                        .eq(Location::getLocationStatus, LocationStatus.OCCUPY.getCode()));
                // 反馈失败
                logger.error("处理载具入库请求失败！");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("处理载具入库请求失败！");
                return convertJsonString(response);
            }

            logger.info("处理载具入库请求成功！");
            response.setCode(ResponseCode.OK.getCode());
            response.setMessage("处理载具入库请求成功！");
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("处理载具入库请求发生异常：{}", e.getMessage());
            // 返回其他异常
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("处理载具入库请求发生异常");
            return convertJsonString(response);
        }
    }

    /**
     * Wcs反馈重复入库问题
     *
     * @param duplicateLocationRequest 重复入库反馈请求
     * @return 结果
     */
    @PostMapping("/duplicateLocationOccurred")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    @MyLog(logTitle = "Wcs反馈重复入库问题", logMethod = "duplicateLocationOccurred")
    public String ResolveDuplicateLocation(@RequestBody WcsTaskResultRequest duplicateLocationRequest) {
        logger.info("接收到Wcs反馈重复入库问题：{}，ip地址：{}", convertJsonString(duplicateLocationRequest), HttpUtils.getIpAddr(servletRequest));
        // 创建响应信息
        ResponseEntity response = new ResponseEntity();
        try {
            // 验证入库请求
            String validationInfo = validateService.validateDuplicateLocationRequest(duplicateLocationRequest);
            if (!Objects.equals(validationInfo, "")) {
                logger.error("反馈重复入库错误：{}", validationInfo);
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("反馈重复入库错误：" + validationInfo);
                return convertJsonString(response);
            }
            // 请求可用库位
            String nextLocationId = "";
            for (int i = 0; i < locationService.count(new LambdaQueryWrapper<Location>().eq(Location::getLocationStatus, LocationStatus.EMPTY.getCode())); i++) {
                Map<String, String> resultMap = locationService.getOneLocation("", "");
                if (resultMap.isEmpty() || !resultMap.containsKey("nextLocationId")) {
                    logger.error("暂无可用库位");
                    response.setCode(ResponseCode.ERROR.getCode());
                    response.setMessage("暂无可用库位！");
                    return convertJsonString(response);
                } else {
                    Location nextLocation = locationService.getOne(new LambdaQueryWrapper<Location>().eq(Location::getLocationId, resultMap.get("nextLocationId")).last("limit 1"));
                    LambdaUpdateWrapper<Location> updateLocationWrapper = new LambdaUpdateWrapper<Location>()
                            .set(Location::getLocationStatus, LocationStatus.OCCUPY.getCode())
                            .set(Location::getVehicleId, duplicateLocationRequest.getVehicleId())
                            .eq(Location::getLocationId, nextLocation.getLocationId())
                            .eq(Location::getLocationStatus, LocationStatus.EMPTY.getCode());
                    if (locationService.update(updateLocationWrapper)) {
                        nextLocationId = resultMap.get("nextLocationId");
                        break;
                    }
                }
            }
            if (Objects.equals(nextLocationId, "")) {
                logger.error("暂无可用库位");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("暂无可用库位！");
                return convertJsonString(response);
            }
            // 找到库位，更新任务
            LambdaUpdateWrapper<Task> lambdaUpdateWrapperOfTask = new LambdaUpdateWrapper<Task>()
                    .set(Task::getDestination, nextLocationId)
                    .set(Task::getTaskStatus, WmsTaskStatus.DUPLICATE.getCode())
                    .eq(Task::getVehicleId, duplicateLocationRequest.getVehicleId())
                    .eq(Task::getTaskGroup, duplicateLocationRequest.getTaskId())
                    .ne(Task::getTaskStatus, WmsTaskStatus.DUPLICATE.getCode());
            if (!taskService.update(lambdaUpdateWrapperOfTask)) {
                // 回退库位锁定
                locationService.update(new LambdaUpdateWrapper<Location>()
                        .set(Location::getLocationStatus, LocationStatus.EMPTY.getCode())
                        .set(Location::getVehicleId, "")
                        .eq(Location::getLocationId, nextLocationId)
                        .eq(Location::getLocationStatus, LocationStatus.OCCUPY.getCode()));
                // 反馈失败
                logger.error("处理重复入库请求失败！");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("处理重复入库请求失败！");
                return convertJsonString(response);
            }

            logger.info("处理载具入库请求成功！");
            response.setCode(ResponseCode.OK.getCode());
            response.setMessage("处理载具入库请求成功！");
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("处理载具入库请求发生异常：{}", e.getMessage());
            // 返回其他异常
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("处理载具入库请求发生异常");
            return convertJsonString(response);
        }
    }

    /**
     * 查找所有任务
     */
    @PostMapping("/getTasksByPage")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    public String getTasksByPage(@RequestBody TaskQuery taskQuery) {
        ResponseEntity response = new ResponseEntity();
        try {
            Page<Task> page = taskQuery.toMpPage();
            //更新条件
            LambdaQueryWrapper<Task> lambdaQueryWrapper = new LambdaQueryWrapper<Task>()
                    .eq(taskQuery.getTaskType() != null, Task::getTaskType, taskQuery.getTaskType())
                    .eq(taskQuery.getTaskStatus() != null, Task::getTaskStatus, taskQuery.getTaskStatus())
                    .like(StringUtils.isNotEmpty(taskQuery.getVehicleId()), Task::getVehicleId, taskQuery.getVehicleId())
                    .apply(StringUtils.isNotEmpty(taskQuery.getGoodsId()), "goods_related ->> '$.goodsId' like concat('%', {0}, '%')" + MYSQL_JSON_CI, taskQuery.getGoodsId())
                    .apply(StringUtils.isNotEmpty(taskQuery.getGoodsName()), "goods_related ->> '$.goodsName' like concat('%', {0}, '%')" + MYSQL_JSON_CI, taskQuery.getGoodsName());
            Page<Task> tasksPage = taskService.page(page, lambdaQueryWrapper);
            // 生成数据
            PageDto<TaskVO> pageDto = PageDto.of(tasksPage, tasks -> BeanUtil.copyProperties(tasks, TaskVO.class));
            response.setCode(ResponseCode.OK.getCode());
            response.setMessage("查询成功");
            response.setReturnData(pageDto);
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("查询任务发生异常");
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("查询任务发生异常");
            return convertJsonString(response);
        }
    }

    /**
     * 根据请求参数查询任务信息
     */
    @PostMapping("/getTasks")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    public String getTasks(@RequestBody TaskQuery taskQuery) {
        ResponseEntity response = new ResponseEntity();
        try {
            //更新条件
            LambdaQueryWrapper<Task> lambdaQueryWrapper = new LambdaQueryWrapper<Task>()
                    .eq(taskQuery.getTaskType() != null, Task::getTaskType, taskQuery.getTaskType())
                    .eq(taskQuery.getTaskStatus() != null, Task::getTaskStatus, taskQuery.getTaskStatus())
                    .eq(taskQuery.getIsPicking() != null, Task::getIsPicking, taskQuery.getIsPicking())
                    .like(StringUtils.isNotEmpty(taskQuery.getVehicleId()), Task::getVehicleId, taskQuery.getVehicleId())
                    .apply(StringUtils.isNotEmpty(taskQuery.getGoodsId()), "goods_related ->> '$.goodsId' like concat('%', {0}, '%')" + MYSQL_JSON_CI, taskQuery.getGoodsId())
                    .apply(StringUtils.isNotEmpty(taskQuery.getGoodsName()), "goods_related ->> '$.goodsName' like concat('%', {0}, '%')" + MYSQL_JSON_CI, taskQuery.getGoodsName());
            List<Task> tasks = taskService.list(lambdaQueryWrapper);
            response.setCode(ResponseCode.OK.getCode());
            response.setMessage("查询成功");
            response.setReturnData(tasks.isEmpty() ? new ArrayList<Task>() : tasks);
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("查询任务发生异常");
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("查询任务发生异常");
            return convertJsonString(response);
        }
    }

    /**
     * WCS向WMS上报箱子到达
     *
     * @param boxArriveRequest 请求参数
     * @return 结果
     */
    @PostMapping("/boxArrive")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    @MyLog(logTitle = "Wcs上报箱子到达", logMethod = "boxArrive")
    public String boxArrive(@RequestBody WcsBoxArriveRequest boxArriveRequest) {
        logger.info("接收到Wcs上报箱子到达：{}，ip地址：{}", convertJsonString(boxArriveRequest), HttpUtils.getIpAddr(servletRequest));
        ResponseEntity response = new ResponseEntity();
        try {
            // 校验请求参数
            String validateInfo = validateService.validateBoxArriveRequest(boxArriveRequest);
            if (!Objects.equals(validateInfo, "")) {// 验证未通过
                logger.error("Wcs上报箱子到达验证错误：{}", validateInfo);
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage(validateInfo);
                return convertJsonString(response);
            }
            // 查找到对应的拣选任务
            PickTask pickTask = pickTaskService.getOne(new LambdaQueryWrapper<PickTask>()
                    .eq(PickTask::getVehicleId, boxArriveRequest.getVehicleNo())
                    .eq(PickTask::getStandId, boxArriveRequest.getLocation())
                    .last("limit 1"));
            if (pickTask == null || StringUtils.isEmpty(pickTask.getPickTaskId())) {
                logger.error("拣选任务查询失败");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("拣选任务查询失败");
                return convertJsonString(response);
            }
            pickTask.setPickStatus(PickTaskStatusEnum.FINISH.getCode());
            pickTask.setLastUpdateTime(LocalDateTime.now());
            // 更新为完成
            pickTaskService.updateById(pickTask);
            // 更新站台信息
            standService.update(new LambdaUpdateWrapper<Stand>()
                    .set(Stand::getPickVehicle, boxArriveRequest.getVehicleNo())
                    .eq(Stand::getStandId, pickTask.getStandId()));
            // 重置当前站台非当前箱子的已完成拣选任务
            List<PickTask> otherPickTasks = pickTaskService.list(new LambdaQueryWrapper<PickTask>()
                    .ne(PickTask::getVehicleId, boxArriveRequest.getVehicleNo())
                    .eq(PickTask::getStandId, boxArriveRequest.getLocation())
                    .eq(PickTask::getPickStatus, PickTaskStatusEnum.FINISH.getCode()));
            otherPickTasks.forEach(otherPickTask -> otherPickTask.setPickStatus(PickTaskStatusEnum.NEW.getCode()));
            pickTaskService.updateBatchById(otherPickTasks);

            response.setCode(ResponseCode.OK.getCode());
            response.setMessage("上报成功");
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("上报时发生异常：{}", convertJsonString(e));
            // 返回其他异常
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("上报时发生异常");
            return convertJsonString(response);
        }
    }

    /**
     * 根据站台号以及料号获取工作信息给前台界面展示
     *
     * @param workQuery 查询参数
     * @return 生成的vo信息
     */
    @PostMapping("/getWorkByStandAndGoods")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    @MyLog(logTitle = "获取备料工作信息", logMethod = "getWorkByStandAndGoods")
    public String getWorkByStandAndGoods(@RequestBody WorkQuery workQuery) {
        logger.info("接收到获取备料工作信息请求：{}，ip地址：{}", convertJsonString(workQuery), HttpUtils.getIpAddr(servletRequest));
        ResponseEntity response = new ResponseEntity();
        try {
            String validateInfo = validateService.validateGetWorkVoRequest(workQuery);
            if (!Objects.equals(validateInfo, "")) {
                logger.error("获取备料工作请求参数验证错误：{}", validateInfo);
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage(validateInfo);
                return convertJsonString(response);
            }
            String standId = "";
            if (StringUtils.isNotEmpty(workQuery.getStandId())) {
                // 站台号从请求参数中获取
                standId = workQuery.getStandId();
            } else {
                // 站台号从ip获取
                Stand standOfIp = standService.getOne(new LambdaQueryWrapper<Stand>()
                        .eq(Stand::getStandIp, HttpUtils.getIpAddr(servletRequest))
                        .eq(Stand::getStandType, 2)
                        .last("limit 1"));
                if (standOfIp != null && StringUtils.isNotEmpty(standOfIp.getStandId())) {
                    standId = standOfIp.getStandId();
                }
            }
            if (StringUtils.isEmpty(standId)) {
                logger.error("获取不到正确的站台号");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("获取不到正确的站台号");
                return convertJsonString(response);
            }
            // 根据站台号查找对应的载具号
            PickTask pickTask = pickTaskService.getOne(new LambdaQueryWrapper<PickTask>()
                    .eq(PickTask::getStandId, standId)
                    .eq(PickTask::getPickStatus, PickTaskStatusEnum.FINISH.getCode())
                    .last("limit 1"));
            if (pickTask == null || StringUtils.isEmpty(pickTask.getVehicleId())) {
                logger.error("当前站台查不到正在拣选的箱子");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("当前站台查不到正在拣选的箱子，请尝试拣选界面修改当前料箱状态。");
                return convertJsonString(response);
            }
            String vehicleId = pickTask.getVehicleId();
            // 查找库存信息
            Stock stock = stockService.getOne(new LambdaQueryWrapper<Stock>()
                    .eq(Stock::getVehicleId, vehicleId)
                    .apply("goods_related ->> '$.goodsId' = {0}" + MYSQL_JSON_CI, workQuery.getGoodsId())
                    .last("limit 1"));
            if (stock == null || StringUtils.isEmpty(stock.getStockId()) || stock.getGoodsRelated() == null) {
                logger.error("请求料号：{}与正在拣选的箱子：{}无对应关系", workQuery.getGoodsId(), vehicleId);
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("请求料号：" + workQuery.getGoodsId() + "与正在拣选的箱子：" + vehicleId + "无对应关系，请扫描其他料号或者按按钮。");
                return convertJsonString(response);
            }
            // 查一下物料信息
            Goods goodsInfo = goodsService.getOne(new LambdaQueryWrapper<Goods>()
                    .eq(Goods::getGoodsId, workQuery.getGoodsId())
                    .last("limit 1"));
            // 查找工作流
            List<WorkFlow> workFlows = workFlowService.list(new LambdaQueryWrapper<WorkFlow>()
                    .eq(WorkFlow::getWorkStation, standId)
                    .eq(WorkFlow::getGoodsId, workQuery.getGoodsId())
                    .eq(WorkFlow::getWorkStatus, 1)
                    .ne(WorkFlow::getLightStatus, 2)
                    .apply("picked_num < need_num")
                    .orderByDesc(WorkFlow::getLightStatus));
            if (workFlows == null || workFlows.isEmpty()) {
                logger.error("当前站台当前物料查询不到对应的工作");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("当前站台当前物料查询不到对应的工作，请扫描其他料号或者按按钮。");
                return convertJsonString(response);
            }
            // 亮灯
            BigDecimal originNum = stock.getGoodsRelated().getRemainNum();
            BigDecimal realNum = stock.getGoodsRelated().getRemainNum();
            List<ETaskData> eTaskDataList = new ArrayList<>();
            for (WorkFlow tempWork : workFlows) {
                if (realNum.compareTo(BigDecimal.ZERO) <= 0) {// 当前物料数量不足
                    break;
                }
                if (tempWork.getLightStatus() != 0) {
                    // 不是未亮灯的状态
                    // 当次拣选数量
                    BigDecimal thisPickNum = realNum.compareTo(tempWork.getNeedNum().subtract(tempWork.getPickedNum())) > 0 ? tempWork.getNeedNum().subtract(tempWork.getPickedNum()) : realNum;
                    realNum = realNum.subtract(thisPickNum);
                    continue;
                }
                // 查找对应的标签配置
                ELocationConfig eConfig = eLocationConfigService.getOne(new LambdaQueryWrapper<ELocationConfig>()
                        .eq(ELocationConfig::getWorkStation, standId)
                        .eq(ELocationConfig::getWorkOrder, tempWork.getWorkOrder())
                        .eq(ELocationConfig::getWorkCenter, tempWork.getWorkCenter())
                        .last("limit 1"));
                if (eConfig != null) {
                    // 当次拣选数量
                    BigDecimal thisPickNum = realNum.compareTo(tempWork.getNeedNum().subtract(tempWork.getPickedNum())) > 0 ? tempWork.getNeedNum().subtract(tempWork.getPickedNum()) : realNum;
                    ETaskData eTaskData = new ETaskData();
                    eTaskData.setTaskId(tempWork.getWorkFlowId());// 用户查询对应的拣选任务
                    eTaskData.setETaskId(generateId("ETASK_"));
                    eTaskData.setGoodsId(tempWork.getGoodsId());
                    eTaskData.setGoodsName(goodsInfo != null ? goodsInfo.getGoodsName() : "");
                    eTaskData.setNeedNum(thisPickNum.intValue());
                    eTaskData.setLocation(eConfig.getELocationId());
                    eTaskDataList.add(eTaskData);
                    // 更新电子标签库位信息
                    etagLocationService.update(new LambdaUpdateWrapper<ETagLocation>()
                            .set(ETagLocation::getTaskId, eTaskData.getTaskId())
                            .set(ETagLocation::getNeedNum, eTaskData.getNeedNum())
                            .set(ETagLocation::getConfirmNum, eTaskData.getNeedNum())
                            .eq(ETagLocation::getELocationId, eConfig.getELocationId()));
                    // 设置工作流更新信息
//                    tempWork.setPickedNum(tempWork.getPickedNum().add(thisPickNum));
                    tempWork.setLightStatus(1);
                    tempWork.setOpUser(workQuery.getUserName());
                    realNum = realNum.subtract(thisPickNum);
                }
            }
            if (!eTaskDataList.isEmpty()) {
                // 发送亮灯
                WcsETaskRequest wcsETaskRequest = new WcsETaskRequest();
                wcsETaskRequest.setTaskGroup(generateId(vehicleId + "_"));
                wcsETaskRequest.setTaskType(1);
                wcsETaskRequest.setTaskData(eTaskDataList);
                wcsETaskRequest.setOrderId(generateId(workQuery.getGoodsId() + "_"));
                wcsETaskRequest.setVehicleNo(vehicleId);
                String sendToWcsETaskUrl = configMap.get(ConfigMapKeyEnum.URL_WCS_E_TASK.getConfigKey());
                if (StringUtils.isEmpty(sendToWcsETaskUrl)) {
                    // url地址为空
                    logger.error("向Wcs发送电子标签亮灯任务的地址为空");
                    throw new Exception("向Wcs发送电子标签亮灯任务的地址为空");
                } else {
                    // 发送信息
                    logger.info("发送电子标签亮灯请求：{}", convertJsonString(wcsETaskRequest));
                    ResponseEntity result = JSON.parseObject(HttpUtils.sendHttpPostWithoutToken(sendToWcsETaskUrl, convertJsonString(wcsETaskRequest)), ResponseEntity.class);
                    try {
                        logService.save(new WmsLog(WmsUtils.generateId("LOG_"), "发送电子标签任务", "eTagTask", convertJsonString(wcsETaskRequest), convertJsonString(result), sendToWcsETaskUrl, LocalDateTime.now(), "WMS"));
                    } catch (Exception e) {
                        logger.error("插入日志错误");
                    }
                    if (result == null || !Objects.equals(result.getCode(), ResponseCode.OK.getCode())) {
                        logger.error("发送电子标签亮灯任务失败：{}", convertJsonString(result));
                        throw new Exception("发送电子标签亮灯任务失败");
                    } else {
                        // 更新workFlow数据
                        workFlowService.updateBatchById(workFlows);
                        // 更新亮灯数据
                        etagLocationService.update(new LambdaUpdateWrapper<ETagLocation>()
                                .set(ETagLocation::getPickStatus, 1)
                                .set(ETagLocation::getTaskType, wcsETaskRequest.getTaskType())
                                .set(ETagLocation::getVehicleNo, wcsETaskRequest.getVehicleNo())
                                .in(ETagLocation::getELocationId, eTaskDataList.stream().map(ETaskData::getLocation).collect(Collectors.toList())));
                    }
                }
            }
            // 更新站台数据
            standService.update(new LambdaUpdateWrapper<Stand>()
                    .set(Stand::getPickGoods, workQuery.getGoodsId())
                    .set(Stand::getPickVehicle, vehicleId)
                    .eq(Stand::getStandId, standId));
            // 生成前台VO
            StandPickVo standPickVo = new StandPickVo();
            standPickVo.setStandId(standId);
            standPickVo.setGoodsId(workQuery.getGoodsId());
            standPickVo.setPlanPickNum(originNum.subtract(realNum));
            standPickVo.setRemainNumOrigin(realNum);
            standPickVo.setRemainNumReal(realNum);
            // 获取完成工作信息
            getFinishedInfo(standId, standPickVo);
            standPickVo.setRemark(goodsInfo != null ? goodsInfo.getUnpackingType() : "");
            // 返回成功
            response.setCode(ResponseCode.OK.getCode());
            response.setMessage("获取工作信息成功");
            response.setReturnData(standPickVo);
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("获取工作信息异常：{}", convertJsonString(e));
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("获取工作信息异常：" + e.getMessage());
            return convertJsonString(response);
        }
    }

    /**
     * 查询当前站台的正在拣选的物料是否完成
     *
     * @param workQuery 查询参数
     * @return 生成的vo信息
     */
    @PostMapping("/queryFinishByStandAndGoods")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    public String queryFinishByStandAndGoods(@RequestBody WorkQuery workQuery) {
        ResponseEntity response = new ResponseEntity();
        try {
            String validateInfo = validateService.validateGetWorkVoRequest(workQuery);
            if (!Objects.equals(validateInfo, "")) {
                logger.error("查询当前站台的正在拣选的物料是否完成错误：{}", validateInfo);
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage(validateInfo);
                return convertJsonString(response);
            }
            Stand targetStand;
            if (StringUtils.isNotEmpty(workQuery.getStandId())) {
                // 站台号从请求参数中获取
                targetStand = standService.getById(workQuery.getStandId());
            } else {
                // 站台号从ip获取
                targetStand = standService.getOne(new LambdaQueryWrapper<Stand>()
                        .eq(Stand::getStandIp, HttpUtils.getIpAddr(servletRequest))
                        .eq(Stand::getStandType, 2)
                        .last("limit 1"));
            }
            if (targetStand == null) {
                logger.error("查询拣选站台错误。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("查询拣选站台错误。");
                return convertJsonString(response);
            }
            StandPickVo standPickVo = new StandPickVo();
            if (StringUtils.isEmpty(targetStand.getPickGoods())) {
                // 返回成功
                standPickVo.setTip(targetStand.getPickTip());
                response.setCode(ResponseCode.OK.getCode());
                response.setMessage("当前物料拣货完成。");
            } else {
                // 查询当前站台的拣货任务
                PickTask pickTask = pickTaskService.getOne(new LambdaQueryWrapper<PickTask>()
                        .eq(PickTask::getStandId, targetStand.getStandId())
                        .eq(PickTask::getPickStatus, PickTaskStatusEnum.FINISH.getCode())
                        .last("limit 1"));
                if (pickTask == null) {
                    // 返回成功
                    response.setCode(ResponseCode.OK.getCode());
                    response.setMessage("当前物料拣货完成。");
                } else {
                    if (!targetStand.getPickGoods().equals(workQuery.getGoodsId())) {
                        // 返回成功
                        response.setCode(ResponseCode.OK.getCode());
                        response.setMessage("正在拣选其他物料。");
                    } else {
                        // 返回成功
                        response.setCode(ResponseCode.ERROR.getCode());
                        response.setMessage("当前物料正在拣货");
                    }
                }
            }
            // 获取完成工作信息
            getFinishedInfo(targetStand.getStandId(), standPickVo);
            response.setReturnData(standPickVo);
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("获取工作信息异常：{}", convertJsonString(e));
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("获取工作信息异常");
            return convertJsonString(response);
        }
    }

    /**
     * 获取已完成行数信息
     *
     * @param standPickVo 查询
     */
    public void getFinishedInfo(String workStation, StandPickVo standPickVo) {
        try {
            // 获取当前站台所有的工作流信息
            List<WorkFlow> allWorkFlows = workFlowService.list(new LambdaQueryWrapper<WorkFlow>().eq(WorkFlow::getWorkStation, workStation));
            int finishingRows = 0;
            BigDecimal finishedCounts = BigDecimal.ZERO;
            BigDecimal allCounts = BigDecimal.ZERO;
            for (WorkFlow workFlow : allWorkFlows) {
                if (workFlow.getWorkStatus() == 2) {
                    finishingRows++;
                }
                finishedCounts = finishedCounts.add(workFlow.getPickedNum());
                allCounts = allCounts.add(workFlow.getNeedNum());
            }
            standPickVo.setFinishedRows(finishingRows);
            standPickVo.setTotalRows(allWorkFlows.size());
            standPickVo.setFinishedCounts(finishedCounts);
            standPickVo.setTotalCounts(allCounts);
        } catch (Exception e) {
            logger.error("获取已完成数据报表失败，可能存在类型转换错误");
        }
    }

    /**
     * 获取电子标签反馈
     *
     * @param eTaskFeedbackRequest 反馈信息
     * @return 结果
     */
    @PostMapping("/getETaskFeedBack")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    @MyLog(logTitle = "获取电子标签反馈", logMethod = "getETaskFeedBack")
    public String getETaskFeedBack(@RequestBody WcsETaskFeedbackRequest eTaskFeedbackRequest) {
        logger.info("获取电子标签反馈：{}，ip地址：{}", convertJsonString(eTaskFeedbackRequest), HttpUtils.getIpAddr(servletRequest));
        ResponseEntity response = new ResponseEntity();
        try {
            if (eTaskFeedbackRequest == null || StringUtils.isEmpty(eTaskFeedbackRequest.getTaskId()) || eTaskFeedbackRequest.getTaskType() == null) {
                logger.error("请求参数补全，缺少任务号、任务类型。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("请求参数补全，缺少任务号、任务类型。");
                return convertJsonString(response);
            }
            if (eTaskFeedbackRequest.getTaskType() == 1) {// 拣选任务
                // 查询到对应的库位，如果不是亮灯状态，不接受反馈
                if (!etagLocationService.exists(new LambdaQueryWrapper<ETagLocation>()
                        .eq(ETagLocation::getELocationId, eTaskFeedbackRequest.getLocation())
                        .eq(ETagLocation::getPickStatus, 1))) {
                    logger.error("当前位置无亮灯信息。");
                    response.setCode(ResponseCode.ERROR.getCode());
                    response.setMessage("当前位置无亮灯信息。");
                    return convertJsonString(response);
                }
                // 根据taskId查找对应的workFlow
                WorkFlow workFlow = workFlowService.getOne(new LambdaQueryWrapper<WorkFlow>().eq(WorkFlow::getWorkFlowId, eTaskFeedbackRequest.getTaskId()).last("limit 1"));
                if (workFlow == null) {
                    logger.error("反馈的任务号查找不到对应的工作信息。");
                    response.setCode(ResponseCode.ERROR.getCode());
                    response.setMessage("反馈的任务号查找不到对应的工作信息。");
                    return convertJsonString(response);
                } else {
                    if (workFlow.getPickedNum().compareTo(workFlow.getNeedNum()) >= 0) {
                        logger.error("当前工作拣货数量已足够，请勿重复拍灯。");
                        response.setCode(ResponseCode.ERROR.getCode());
                        response.setMessage("当前工作拣货数量已足够，请勿重复拍灯。");
                        return convertJsonString(response);
                    }
                }
                // 更新实际拣选数量
                workFlow.setPickedNum(workFlow.getPickedNum().add(BigDecimal.valueOf(eTaskFeedbackRequest.getConfirmNum())));
                if (eTaskFeedbackRequest.getConfirmNum().compareTo(eTaskFeedbackRequest.getNeedNum()) < 0) {
                    int diffNum = eTaskFeedbackRequest.getNeedNum() - eTaskFeedbackRequest.getConfirmNum();
                    // 查站台要料表---未分配以及分配但未完全分配
                    GoodsToStation goodsToStation = goodsToStationService.getOne(new LambdaQueryWrapper<GoodsToStation>()
                            .eq(GoodsToStation::getWorkStation, workFlow.getWorkStation())
                            .eq(GoodsToStation::getGoodsId, workFlow.getGoodsId())
                            .last("limit 1"));
                    if (goodsToStation != null) {
                        // 更新站台要料数量
                        BigDecimal newDistributeNum = goodsToStation.getDistributedNum().subtract(BigDecimal.valueOf(diffNum));
                        goodsToStation.setDistributedNum(newDistributeNum.compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO : newDistributeNum);
                        goodsToStation.setDistributeStatus(1);
                        goodsToStationService.updateById(goodsToStation);
                    }
                    // 查询当前站台的拣货任务
                    PickTask pickTask = pickTaskService.getOne(new LambdaQueryWrapper<PickTask>()
                            .eq(PickTask::getStandId, workFlow.getWorkStation())
                            .eq(PickTask::getPickStatus, PickTaskStatusEnum.FINISH.getCode())
                            .last("limit 1"));
                    if (pickTask != null) {
                        // 更新当前的outsideVehicles状态为一个新状态，拉取任务时不拉取它
                        List<OutsideVehicles> outsideVehiclesList = outsideVehiclesService.list(new LambdaQueryWrapper<OutsideVehicles>()
                                .eq(OutsideVehicles::getVehicleId, pickTask.getVehicleId())
                                .eq(OutsideVehicles::getGoodsId, workFlow.getGoodsId()));
                        for (OutsideVehicles outsideVehicles : outsideVehiclesList) {
                            outsideVehicles.setOutStatus(2);
                        }
                        outsideVehiclesService.updateBatchById(outsideVehiclesList);
                    }
                    // 更新workFlow状态
                    workFlow.setLightStatus(0);// 未亮灯
                    workFlow.setWorkStatus(1);// 正在做
                } else {
                    if (workFlow.getPickedNum().compareTo(workFlow.getNeedNum()) < 0) {
                        // 缺料未完成
                        workFlow.setLightStatus(0);// 未亮灯
                        workFlow.setWorkStatus(1);// 正在做
                    } else {
                        workFlow.setLightStatus(2);// 已拍灯
                        workFlow.setWorkStatus(2);// 已完成
                    }
                }
                // 更新workFlow
                workFlow.setFinishTime(LocalDateTime.now());
                workFlowService.updateById(workFlow);
                // 更新库存数量
                Stock existStock = stockService.getOne(new LambdaQueryWrapper<Stock>()
                        .apply("goods_related ->> '$.goodsId' = {0}" + MYSQL_JSON_CI, workFlow.getGoodsId())
                        .eq(Stock::getVehicleId, eTaskFeedbackRequest.getVehicleNo())
                        .last("limit 1"));
                if (existStock != null && existStock.getGoodsRelated() != null) {
                    Stock originStock = BeanUtil.copyProperties(existStock, Stock.class);
                    BigDecimal quantityBefore = originStock.getGoodsRelated().getRemainNum();
                    StockDetailInfo goodsDetail = existStock.getGoodsRelated();
                    goodsDetail.setRemainNum(goodsDetail.getRemainNum().subtract(BigDecimal.valueOf(eTaskFeedbackRequest.getConfirmNum())));
                    existStock.setGoodsRelated(goodsDetail);
                    stockService.updateById(existStock);
                    stockUpdateRecordService.addStockUpdateRecord(originStock, existStock, StockUpdateReasonEnum.KITTING_UPDATE.getReason(), workFlow.getWorkStation() + "-电子标签灯光反馈", quantityBefore);
                }
                // 更新电子标签库位信息
                etagLocationService.update(new LambdaUpdateWrapper<ETagLocation>()
                        .set(ETagLocation::getPickStatus, 0)
                        .set(ETagLocation::getTaskId, "")
                        .set(ETagLocation::getVehicleNo, "")
                        .set(ETagLocation::getTaskType, null)
                        .set(ETagLocation::getNeedNum, null)
                        .set(ETagLocation::getConfirmNum, null)
                        .eq(ETagLocation::getELocationId, eTaskFeedbackRequest.getLocation()));
            } else {// 小盒子放入大盒子
                // 根据location查询到对应的配置
                ELocationConfigLast eLocationConfigLast = eLocationConfigLastService.getOne(new LambdaQueryWrapper<ELocationConfigLast>()
                        .eq(ELocationConfigLast::getELocationId, eTaskFeedbackRequest.getLocation())
                        .last("limit 1"));
                if (eLocationConfigLast != null) {
                    // 设置状态为已取走
                    eLocationConfigLast.setBoxStatus(2);
                    eLocationConfigLastService.updateById(eLocationConfigLast);
                }
                // 更新电子标签库位信息
                etagLocationService.update(new LambdaUpdateWrapper<ETagLocation>()
                        .set(ETagLocation::getPickStatus, 0)
                        .set(ETagLocation::getTaskId, "")
                        .set(ETagLocation::getVehicleNo, "")
                        .set(ETagLocation::getTaskType, null)
                        .set(ETagLocation::getNeedNum, null)
                        .set(ETagLocation::getConfirmNum, null)
                        .eq(ETagLocation::getELocationId, eTaskFeedbackRequest.getLocation()));
            }
            response.setCode(ResponseCode.OK.getCode());
            response.setMessage("处理反馈成功");
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("处理反馈异常：{}", convertJsonString(e));
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("处理反馈异常");
            return convertJsonString(response);
        }
    }

    /**
     * 确认完成---wms界面触发
     *
     * @param workConfirmRequest 请求信息
     * @return 结果
     */
    @PostMapping("/confirmFinishWork")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    @MyLog(logTitle = "确认当前拣货完成（wms界面触发）", logMethod = "confirmFinishWork")
    public String confirmFinishWork(@RequestBody WorkConfirmRequest workConfirmRequest) {
        logger.info("接收到确认当前拣货完成（wms界面触发）请求：{}，ip地址：{}", convertJsonString(workConfirmRequest), HttpUtils.getIpAddr(servletRequest));
        ResponseEntity response = new ResponseEntity();
        try {
            // 获取站台号
            String standId = "";
            if (StringUtils.isNotEmpty(workConfirmRequest.getStandId())) {
                // 站台号从请求参数中获取
                standId = workConfirmRequest.getStandId();
            } else {
                // 站台号从ip获取
                Stand standOfIp = standService.getOne(new LambdaQueryWrapper<Stand>()
                        .eq(Stand::getStandIp, HttpUtils.getIpAddr(servletRequest))
                        .eq(Stand::getStandType, 2)
                        .last("limit 1"));
                if (standOfIp != null && StringUtils.isNotEmpty(standOfIp.getStandId())) {
                    standId = standOfIp.getStandId();
                }
            }
            if (StringUtils.isEmpty(standId)) {
                logger.error("请求参数缺少站台号。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("请求参数缺少站台号。");
                return convertJsonString(response);
            }
            if (StringUtils.isEmpty(workConfirmRequest.getGoodsId())) {
                logger.error("请求参数缺少料号。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("请求参数缺少料号。");
                return convertJsonString(response);
            }
            // 判断当前站台是否还有亮灯数据
            if (etagLocationService.exists(new LambdaQueryWrapper<ETagLocation>()
                    .eq(ETagLocation::getWorkStation, standId)
                    .eq(ETagLocation::getPickStatus, 1))) {
                logger.error("站台灯光未全部拍灭，请检查。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("站台灯光未全部拍灭，请检查。");
                return convertJsonString(response);
            }
            // 查询当前站台的拣货任务
            PickTask pickTask = pickTaskService.getOne(new LambdaQueryWrapper<PickTask>()
                    .eq(PickTask::getStandId, standId)
                    .eq(PickTask::getPickStatus, PickTaskStatusEnum.FINISH.getCode())
                    .last("limit 1"));
            if (pickTask == null) {
                // 没有拣货任务，直接放行
                // 调用Wcs的放行接口
                wcsService.sendWcsDisposeVehicle(new WcsDisposeVehicleRequest(standId, null));
                // 更新站台信息
                standService.update(new LambdaUpdateWrapper<Stand>()
                        .set(Stand::getLastUseTime, LocalDateTime.now())
                        .set(Stand::getPickVehicle, "")
                        .set(Stand::getPickGoods, "")
                        .set(Stand::getPickTip, "")
                        .eq(Stand::getStandId, standId));
                response.setCode(ResponseCode.OK.getCode());
                response.setMessage("确认成功，放行");
            } else {
                Stock existStock = stockService.getOne(new LambdaQueryWrapper<Stock>()
                        .apply("goods_related ->> '$.goodsId' = {0}" + MYSQL_JSON_CI, workConfirmRequest.getGoodsId())
                        .eq(Stock::getVehicleId, pickTask.getVehicleId())
                        .last("limit 1"));// 更新库存数量
                // 处理库存偏差
                if (workConfirmRequest.getRemainNumReal().compareTo(workConfirmRequest.getRemainNumOrigin()) != 0) {
                    if (existStock != null && existStock.getGoodsRelated() != null) {
                        Stock originStock = BeanUtil.copyProperties(existStock, Stock.class);
                        BigDecimal quantityBefore = originStock.getGoodsRelated().getRemainNum();
                        StockDetailInfo goodsDetail = existStock.getGoodsRelated();
                        goodsDetail.setRemainNum(workConfirmRequest.getRemainNumReal());
                        existStock.setGoodsRelated(goodsDetail);
                        stockService.updateById(existStock);
                        stockUpdateRecordService.addStockUpdateRecord(originStock, existStock, StockUpdateReasonEnum.CONFIRM_UPDATE.getReason(), workConfirmRequest.getUserName(), quantityBefore);
                    }
                    OutsideVehicles currentGoodsVehicle = outsideVehiclesService.getOne(new LambdaQueryWrapper<OutsideVehicles>()
                            .eq(OutsideVehicles::getVehicleId, pickTask.getVehicleId())
                            .eq(OutsideVehicles::getGoodsId, workConfirmRequest.getGoodsId())
                            .last("limit 1"));
                    if (workConfirmRequest.getRemainNumReal().compareTo(BigDecimal.ZERO) == 0) {// 实际剩余数量为0
                        // 更新流转载具表剩余数量
                        if (currentGoodsVehicle != null) {
                            currentGoodsVehicle.setRemainNum(BigDecimal.ZERO);
                            currentGoodsVehicle.setOutStatus(2);
                            outsideVehiclesService.updateById(currentGoodsVehicle);
                        }
                    } else {
                        // 更新流转载具表剩余数量
                        if (currentGoodsVehicle != null) {
                            currentGoodsVehicle.setRemainNum(currentGoodsVehicle.getRemainNum().add(workConfirmRequest.getRemainNumReal().subtract(workConfirmRequest.getRemainNumOrigin())));
                            outsideVehiclesService.updateById(currentGoodsVehicle);
                        }
                    }
                } else {
                    if (existStock != null && existStock.getGoodsRelated() != null) {
                        if (workConfirmRequest.getRemainNumOrigin().compareTo(BigDecimal.ZERO) == 0) {
                            Stock originStock = BeanUtil.copyProperties(existStock, Stock.class);
                            BigDecimal quantityBefore = originStock.getGoodsRelated().getRemainNum();
                            StockDetailInfo goodsDetail = existStock.getGoodsRelated();
                            goodsDetail.setRemainNum(BigDecimal.ZERO);
                            existStock.setGoodsRelated(goodsDetail);
                            stockService.updateById(existStock);
                            stockUpdateRecordService.addStockUpdateRecord(originStock, existStock, StockUpdateReasonEnum.CONFIRM_UPDATE.getReason(), workConfirmRequest.getUserName(), quantityBefore);
                            OutsideVehicles currentGoodsVehicle = outsideVehiclesService.getOne(new LambdaQueryWrapper<OutsideVehicles>()
                                    .eq(OutsideVehicles::getVehicleId, pickTask.getVehicleId())
                                    .eq(OutsideVehicles::getGoodsId, workConfirmRequest.getGoodsId())
                                    .last("limit 1"));
                            currentGoodsVehicle.setRemainNum(BigDecimal.ZERO);
                            currentGoodsVehicle.setOutStatus(2);
                            outsideVehiclesService.updateById(currentGoodsVehicle);
                        }
                    }
                }
                List<String> goodsIdList = new ArrayList<>();
                // 查询库存
                List<Stock> stockList = stockService.list(new LambdaQueryWrapper<Stock>()
                        .eq(Stock::getVehicleId, pickTask.getVehicleId()));
                if (stockList != null && !stockList.isEmpty()) {
                    for (Stock tempStock : stockList) {
                        // 当前确认料号
                        if (Objects.equals(tempStock.getGoodsRelated().getGoodsId(), workConfirmRequest.getGoodsId())) {
                            continue;
                        }
                        if (!goodsIdList.contains(tempStock.getGoodsRelated().getGoodsId())
                                && tempStock.getGoodsRelated().getRemainNum().compareTo(BigDecimal.ZERO) > 0) {
                            goodsIdList.add(tempStock.getGoodsRelated().getGoodsId());
                        }
                    }
                }
                if (goodsIdList.size() > 0) {
                    // 判断这些物料是不是当前站台的工作流中仍然需要
                    if (workFlowService.exists(new LambdaQueryWrapper<WorkFlow>()
                            .eq(WorkFlow::getWorkStation, standId)
                            .in(WorkFlow::getGoodsId, goodsIdList)
                            .ne(WorkFlow::getWorkStatus, 2))) {
                        // 需要，不放行，返回前台提示信息
                        StandPickVo pickVoEntity = new StandPickVo();
                        pickVoEntity.setTip("当前料箱还有其他物料需要拣货");
                        standService.update(new LambdaUpdateWrapper<Stand>()
                                .set(Stand::getPickGoods, "")
                                .set(Stand::getPickTip, pickVoEntity.getTip())
                                .eq(Stand::getStandId, standId));
                        response.setCode(ResponseCode.WARNING.getCode());
                        response.setMessage("当前料箱还有其他物料需要拣货");
                        response.setReturnData(pickVoEntity);
                    } else {
                        // 存储拣选记录
                        PickTaskRecord pickTaskRecord = BeanUtil.copyProperties(pickTask, PickTaskRecord.class);
                        pickTaskRecord.setPickTaskId(generateId(pickTaskRecord.getPickTaskId()));
                        pickTaskRecord.setLastUpdateTime(LocalDateTime.now());
                        pickTaskRecordService.save(pickTaskRecord);
                        // 删除当前拣选任务
                        pickTaskService.removeById(pickTask);
                        // 不需要，放行
                        wcsService.sendWcsDisposeVehicle(new WcsDisposeVehicleRequest(standId, pickTask.getVehicleId()));
                        // 判断是不是已经完成工作
                        if (workFlowService.exists(new LambdaQueryWrapper<WorkFlow>()
                                .eq(WorkFlow::getWorkStation, standId)
                                .ne(WorkFlow::getWorkStatus, 2))) {
                            // 当前站台工作未全部完成
                            standService.update(new LambdaUpdateWrapper<Stand>()
                                    .set(Stand::getLastUseTime, LocalDateTime.now())
                                    .set(Stand::getPickVehicle, "")
                                    .set(Stand::getPickGoods, "")
                                    .set(Stand::getPickTip, "")
                                    .setDecrBy(Stand::getPickVehicleCount, 1)
                                    .eq(Stand::getStandId, standId));
                            response.setMessage("确认成功，放行");
                        } else {
                            standService.update(new LambdaUpdateWrapper<Stand>()
                                    .set(Stand::getLastUseTime, LocalDateTime.now())
                                    .set(Stand::getPickVehicle, "")
                                    .set(Stand::getPickGoods, "")
                                    .set(Stand::getPickTip, "当前工作已经全部完成，请至完成界面进行后续工作。")
                                    .setDecrBy(Stand::getPickVehicleCount, 1)
                                    .eq(Stand::getStandId, standId));
                            StandPickVo pickVoEntity = new StandPickVo();
                            pickVoEntity.setTip("当前工作已经全部完成，请至完成界面进行后续工作。");
                            // 当前站台工作已全部完成，需要提示工作完成，打印标签
                            response.setMessage("当前工作已经全部完成，请至完成界面进行后续工作。");
                            response.setReturnData(pickVoEntity);
                        }
                        response.setCode(ResponseCode.OK.getCode());
                    }
                } else {
                    // 存储拣选记录
                    PickTaskRecord pickTaskRecord = BeanUtil.copyProperties(pickTask, PickTaskRecord.class);
                    pickTaskRecord.setPickTaskId(generateId(pickTaskRecord.getPickTaskId()));
                    pickTaskRecord.setLastUpdateTime(LocalDateTime.now());
                    pickTaskRecordService.save(pickTaskRecord);
                    // 删除当前拣选任务
                    pickTaskService.removeById(pickTask);
                    // 放行
                    wcsService.sendWcsDisposeVehicle(new WcsDisposeVehicleRequest(standId, pickTask.getVehicleId()));
                    // 判断是不是已经完成工作
                    if (workFlowService.exists(new LambdaQueryWrapper<WorkFlow>()
                            .eq(WorkFlow::getWorkStation, standId)
                            .ne(WorkFlow::getWorkStatus, 2))) {
                        // 当前站台工作未全部完成
                        standService.update(new LambdaUpdateWrapper<Stand>()
                                .set(Stand::getLastUseTime, LocalDateTime.now())
                                .set(Stand::getPickVehicle, "")
                                .set(Stand::getPickGoods, "")
                                .set(Stand::getPickTip, "")
                                .setDecrBy(Stand::getPickVehicleCount, 1)
                                .eq(Stand::getStandId, standId));
                        response.setMessage("确认成功，放行");
                    } else {
                        standService.update(new LambdaUpdateWrapper<Stand>()
                                .set(Stand::getLastUseTime, LocalDateTime.now())
                                .set(Stand::getPickVehicle, "")
                                .set(Stand::getPickGoods, "")
                                .set(Stand::getPickTip, "当前工作已经全部完成，请至完成界面进行后续工作。")
                                .setDecrBy(Stand::getPickVehicleCount, 1)
                                .eq(Stand::getStandId, standId));
                        StandPickVo pickVoEntity = new StandPickVo();
                        pickVoEntity.setTip("当前工作已经全部完成，请至完成界面进行后续工作。");
                        // 当前站台工作已全部完成，需要提示工作完成，打印标签
                        response.setMessage("当前工作已经全部完成，请至完成界面进行后续工作。");
                        response.setReturnData(pickVoEntity);
                    }
                    response.setCode(ResponseCode.OK.getCode());
                }
            }
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("确认时发生异常：{}", convertJsonString(e));
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("确认时发生异常");
            return convertJsonString(response);
        }
    }

    /**
     * Wcs请求释放箱子---站台实体按钮触发
     *
     * @param wcsDisposeVehicleRequest 请求信息
     * @return 结果
     */
    @PostMapping("/requestFreeVehicle")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    @MyLog(logTitle = "Wcs请求释放箱子（站台实体按钮触发）", logMethod = "requestFreeVehicle")
    public String requestFreeVehicle(@RequestBody WcsDisposeVehicleRequest wcsDisposeVehicleRequest) {
        logger.info("Wcs请求释放箱子（站台实体按钮触发）：{}，ip地址：{}", convertJsonString(wcsDisposeVehicleRequest), HttpUtils.getIpAddr(servletRequest));
        ResponseEntity response = new ResponseEntity();
        try {
            // 获取站台号
            Stand targetStand;
            if (StringUtils.isNotEmpty(wcsDisposeVehicleRequest.getLocation())) {
                // 站台号从请求参数中获取
                targetStand = standService.getById(wcsDisposeVehicleRequest.getLocation());
            } else {
                // 站台号从ip获取
                targetStand = standService.getOne(new LambdaQueryWrapper<Stand>()
                        .eq(Stand::getStandIp, HttpUtils.getIpAddr(servletRequest))
                        .eq(Stand::getStandType, 2)
                        .last("limit 1"));
            }
            if (targetStand == null) {
                logger.error("查询拣选站台错误。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("查询拣选站台错误。");
                return convertJsonString(response);
            }
            // 判断当前站台是否还有亮灯数据
            if (etagLocationService.exists(new LambdaQueryWrapper<ETagLocation>()
                    .eq(ETagLocation::getWorkStation, targetStand.getStandId())
                    .eq(ETagLocation::getPickStatus, 1))) {
                logger.error("站台灯光未全部拍灭，请检查。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("站台灯光未全部拍灭，请检查。");
                return convertJsonString(response);
            }
            // 查询当前站台的拣货任务
            PickTask pickTask = pickTaskService.getOne(new LambdaQueryWrapper<PickTask>()
                    .eq(PickTask::getStandId, targetStand.getStandId())
                    .eq(PickTask::getPickStatus, PickTaskStatusEnum.FINISH.getCode())
                    .last("limit 1"));
            if (pickTask == null) {
                // 没有拣货任务，直接放行
                // 更新站台信息
                standService.update(new LambdaUpdateWrapper<Stand>()
                        .set(Stand::getLastUseTime, LocalDateTime.now())
                        .set(Stand::getPickVehicle, "")
                        .set(Stand::getPickGoods, "")
                        .set(Stand::getPickTip, "")
                        .eq(Stand::getStandId, targetStand.getStandId()));
                response.setCode(ResponseCode.OK.getCode());
                response.setMessage("确认成功，放行");
            } else {
                List<String> goodsIdList = new ArrayList<>();
                // 查询库存
                List<Stock> stockList = stockService.list(new LambdaQueryWrapper<Stock>()
                        .eq(Stock::getVehicleId, pickTask.getVehicleId()));
                if (stockList != null && !stockList.isEmpty()) {
                    for (Stock tempStock : stockList) {
                        // 当前确认料号
                        if (Objects.equals(tempStock.getGoodsRelated().getGoodsId(), targetStand.getPickGoods())) {
                            continue;
                        }
                        if (!goodsIdList.contains(tempStock.getGoodsRelated().getGoodsId())
                                && tempStock.getGoodsRelated().getRemainNum().compareTo(BigDecimal.ZERO) > 0) {
                            goodsIdList.add(tempStock.getGoodsRelated().getGoodsId());
                        }
                    }
                }
                if (goodsIdList.size() > 0) {
                    // 判断这些物料是不是当前站台的工作流中是否需要
                    if (workFlowService.exists(new LambdaQueryWrapper<WorkFlow>()
                            .eq(WorkFlow::getWorkStation, targetStand.getStandId())
                            .in(WorkFlow::getGoodsId, goodsIdList)
                            .ne(WorkFlow::getWorkStatus, 2))) {
                        // 更新站台信息
                        standService.update(new LambdaUpdateWrapper<Stand>()
                                .set(Stand::getPickGoods, "")
                                .set(Stand::getPickTip, "当前料箱还有其他物料需要拣货")
                                .eq(Stand::getStandId, targetStand.getStandId()));
                        // 需要，不放行，返回前台提示信息
                        response.setCode(ResponseCode.ERROR.getCode());
                        response.setMessage("当前料箱还有其他物料需要拣货");
                    } else {
                        // 存储拣选记录
                        PickTaskRecord pickTaskRecord = BeanUtil.copyProperties(pickTask, PickTaskRecord.class);
                        pickTaskRecord.setPickTaskId(generateId(pickTaskRecord.getPickTaskId()));
                        pickTaskRecord.setLastUpdateTime(LocalDateTime.now());
                        pickTaskRecordService.save(pickTaskRecord);
                        // 删除当前拣选任务
                        pickTaskService.removeById(pickTask);
                        // 不需要，放行
//                        wcsService.sendWcsDisposeVehicle(new WcsDisposeVehicleRequest(targetStand.getStandId(), pickTask.getVehicleId()));
                        // 判断是不是已经完成工作
                        if (workFlowService.exists(new LambdaQueryWrapper<WorkFlow>()
                                .eq(WorkFlow::getWorkStation, targetStand.getStandId())
                                .ne(WorkFlow::getWorkStatus, 2))) {
                            standService.update(new LambdaUpdateWrapper<Stand>()
                                    .set(Stand::getLastUseTime, LocalDateTime.now())
                                    .set(Stand::getPickVehicle, "")
                                    .set(Stand::getPickGoods, "")
                                    .set(Stand::getPickTip, "")
                                    .setDecrBy(Stand::getPickVehicleCount, 1)
                                    .eq(Stand::getStandId, targetStand.getStandId()));
                            // 当前站台工作未全部完成
                            response.setMessage("确认成功，放行");
                        } else {
                            standService.update(new LambdaUpdateWrapper<Stand>()
                                    .set(Stand::getLastUseTime, LocalDateTime.now())
                                    .set(Stand::getPickVehicle, "")
                                    .set(Stand::getPickGoods, "")
                                    .set(Stand::getPickTip, "当前工作已经全部完成，请至完成界面进行后续工作。")
                                    .setDecrBy(Stand::getPickVehicleCount, 1)
                                    .eq(Stand::getStandId, targetStand.getStandId()));
                            // 当前站台工作已全部完成，需要提示工作完成，打印标签
                            response.setMessage("当前工作已经全部完成，请至完成界面进行后续工作。");
                        }
                        response.setCode(ResponseCode.OK.getCode());
                    }
                } else {
                    // 存储拣选记录
                    PickTaskRecord pickTaskRecord = BeanUtil.copyProperties(pickTask, PickTaskRecord.class);
                    pickTaskRecord.setPickTaskId(generateId(pickTaskRecord.getPickTaskId()));
                    pickTaskRecord.setLastUpdateTime(LocalDateTime.now());
                    pickTaskRecordService.save(pickTaskRecord);
                    // 删除当前拣选任务
                    pickTaskService.removeById(pickTask);
                    // 放行
//                    wcsService.sendWcsDisposeVehicle(new WcsDisposeVehicleRequest(targetStand.getStandId(), pickTask.getVehicleId()));
                    // 判断是不是已经完成工作
                    if (workFlowService.exists(new LambdaQueryWrapper<WorkFlow>()
                            .eq(WorkFlow::getWorkStation, targetStand.getStandId())
                            .ne(WorkFlow::getWorkStatus, 2))) {
                        // 当前站台工作未全部完成
                        standService.update(new LambdaUpdateWrapper<Stand>()
                                .set(Stand::getLastUseTime, LocalDateTime.now())
                                .set(Stand::getPickVehicle, "")
                                .set(Stand::getPickGoods, "")
                                .set(Stand::getPickTip, "")
                                .setDecrBy(Stand::getPickVehicleCount, 1)
                                .eq(Stand::getStandId, targetStand.getStandId()));
                        response.setMessage("确认成功，放行");
                    } else {
                        standService.update(new LambdaUpdateWrapper<Stand>()
                                .set(Stand::getLastUseTime, LocalDateTime.now())
                                .set(Stand::getPickVehicle, "")
                                .set(Stand::getPickGoods, "")
                                .set(Stand::getPickTip, "当前工作已经全部完成，请至完成界面进行后续工作。")
                                .setDecrBy(Stand::getPickVehicleCount, 1)
                                .eq(Stand::getStandId, targetStand.getStandId()));
                        // 当前站台工作已全部完成，需要提示工作完成，打印标签
                        response.setMessage("当前工作已经全部完成，请至完成界面进行后续工作。");
                    }
                    response.setCode(ResponseCode.OK.getCode());
                }
            }
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Wcs请求释放箱子异常：{}", convertJsonString(e));
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("Wcs请求释放箱子异常");
            return convertJsonString(response);
        }
    }

    /**
     * 获取当前站台任务完成信息
     *
     * @param workQuery 请求信息
     * @return 结果
     */
    @PostMapping("/getFinishedWorkInfo")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    @MyLog(logTitle = "获取当前站台任务完成信息", logMethod = "getFinishedWorkInfo")
    public String getFinishedWorkInfo(@RequestBody WorkQuery workQuery) {
        logger.info("获取当前站台任务完成信息：{}，ip地址：{}", convertJsonString(workQuery), HttpUtils.getIpAddr(servletRequest));
        ResponseEntity response = new ResponseEntity();
        try {
            // 获取站台号
            String standId = "";
            if (StringUtils.isNotEmpty(workQuery.getStandId())) {
                // 站台号从请求参数中获取
                standId = workQuery.getStandId();
            } else {
                // 站台号从ip获取
                Stand standOfIp = standService.getOne(new LambdaQueryWrapper<Stand>()
                        .eq(Stand::getStandIp, HttpUtils.getIpAddr(servletRequest))
                        .eq(Stand::getStandType, 2)
                        .last("limit 1"));
                if (standOfIp != null && StringUtils.isNotEmpty(standOfIp.getStandId())) {
                    standId = standOfIp.getStandId();
                }
            }
            if (StringUtils.isEmpty(standId)) {
                logger.error("请求参数缺少站台号。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("请求参数缺少站台号。");
                return convertJsonString(response);
            }
            // 生成前台VO
            StandPickFinishVo standPickFinishVo = new StandPickFinishVo();
            standPickFinishVo.setStandId(standId);
            try {
                // 获取当前站台已完成数量
                List<WorkFlow> allWorkFlows = workFlowService.list(new LambdaQueryWrapper<WorkFlow>()
                        .eq(WorkFlow::getWorkStation, standId));
                if (allWorkFlows == null || allWorkFlows.isEmpty()) {
                    standPickFinishVo.setTip("当前站台没有工作");
                    standPickFinishVo.setPlanRows(0);
                    standPickFinishVo.setActualRows(0);
                    standPickFinishVo.setPlanCounts(BigDecimal.ZERO);
                    standPickFinishVo.setActualCounts(BigDecimal.ZERO);
                } else {
                    int finishedRows = 0;
                    BigDecimal finishedCounts = BigDecimal.ZERO;
                    BigDecimal planCounts = BigDecimal.ZERO;
                    for (WorkFlow workFlow : allWorkFlows) {
                        if (workFlow.getWorkStatus() == 2) {
                            finishedRows++;
                        }
                        finishedCounts = finishedCounts.add(workFlow.getPickedNum());
                        planCounts = planCounts.add(workFlow.getNeedNum());
                    }
                    standPickFinishVo.setPlanRows(allWorkFlows.size());
                    standPickFinishVo.setActualRows(finishedRows);
                    standPickFinishVo.setPlanCounts(planCounts);
                    standPickFinishVo.setActualCounts(finishedCounts);
                    if (finishedRows == allWorkFlows.size()) {
                        standPickFinishVo.setTip("工作已经完成，请打印标签");
                    } else {
                        standPickFinishVo.setTip("工作未完成，请继续工作");
                    }
                    if (finishedCounts.compareTo(planCounts) < 0) {
                        standPickFinishVo.setRemark("有缺料，请至异常区处理");
                    } else {
                        standPickFinishVo.setRemark("正常");
                    }
                }
                response.setCode(ResponseCode.OK.getCode());
                response.setMessage("获取工作信息成功");
                response.setReturnData(standPickFinishVo);
            } catch (Exception e) {
                logger.error("获取已完成数据报表失败，可能存在类型转换错误");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("获取已完成数据报表失败，可能存在类型转换错误");
            }

            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("获取当前站台任务完成信息");
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("获取当前站台任务完成信息");
            return convertJsonString(response);
        }
    }

    /**
     * 工作完成确认
     *
     * @param workQuery 请求信息
     * @return 结果
     */
    @PostMapping("/confirmFinishedWork")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    @MyLog(logTitle = "工作完成确认", logMethod = "confirmFinishedWork")
    public String confirmFinishedWork(@RequestBody WorkQuery workQuery) {
        logger.info("工作完成确认：{}，ip地址：{}", convertJsonString(workQuery), HttpUtils.getIpAddr(servletRequest));
        ResponseEntity response = new ResponseEntity();
        try {
            // 获取站台号
            String standId = "";
            if (StringUtils.isNotEmpty(workQuery.getStandId())) {
                // 站台号从请求参数中获取
                standId = workQuery.getStandId();
            } else {
                // 站台号从ip获取
                Stand standOfIp = standService.getOne(new LambdaQueryWrapper<Stand>()
                        .eq(Stand::getStandIp, HttpUtils.getIpAddr(servletRequest))
                        .eq(Stand::getStandType, 2)
                        .last("limit 1"));
                if (standOfIp != null && StringUtils.isNotEmpty(standOfIp.getStandId())) {
                    standId = standOfIp.getStandId();
                }
            }
            if (StringUtils.isEmpty(standId)) {
                logger.error("请求参数缺少站台号。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("请求参数缺少站台号。");
                return convertJsonString(response);
            }
            String finishResult = workService.finishWork(standId);
            if (Objects.equals(finishResult, "")) {
                // 工作完成成功
                response.setCode(ResponseCode.OK.getCode());
                response.setMessage("确认成功，请至收盒子界面完成后续操作。");
            } else {
                // 工作完成失败
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("确认失败：" + finishResult);
            }
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("工作完成确认异常");
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("工作完成确认异常");
            return convertJsonString(response);
        }
    }

    /**
     * 呼叫空箱
     *
     * @param callEmptyVehicleRequest 请求信息
     * @return 结果
     */
    @PostMapping("/callEmptyVehicle")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    @MyLog(logTitle = "呼叫空箱", logMethod = "callEmptyVehicle")
    public String callEmptyVehicle(@RequestBody CallEmptyVehicleRequest callEmptyVehicleRequest) {
        logger.info("呼叫空箱：{}，ip地址：{}", convertJsonString(callEmptyVehicleRequest), HttpUtils.getIpAddr(servletRequest));
        ResponseEntity response = new ResponseEntity();
        try {
            // 验证数量
            if (callEmptyVehicleRequest.getNeedNum() == null || callEmptyVehicleRequest.getNeedNum() <= 0) {
                logger.error("料箱数量必须为大于0的整数");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("料箱数量必须为大于0的整数");
                return convertJsonString(response);
            }
            // 验证请求信息
            if (Objects.equals(callEmptyVehicleRequest.getVehicleType2(), "间接物料")) {
                // TODO 间接物料需要确认
                if (StringUtils.isEmpty(callEmptyVehicleRequest.getGoodsId())) {
                    logger.error("间接物料必须输入物料号");
                    response.setCode(ResponseCode.ERROR.getCode());
                    response.setMessage("间接物料必须输入物料号");
                    return convertJsonString(response);
                }
                // 查询物料是否是间接物料
                Goods goods = goodsService.getOne(new LambdaQueryWrapper<Goods>().eq(Goods::getGoodsId, callEmptyVehicleRequest.getGoodsId()).eq(Goods::getGoodsInVehicleType, "间接物料").last("limit 1"));
                if (goods == null) {
                    logger.error("当前物料不是间接物料");
                    response.setCode(ResponseCode.ERROR.getCode());
                    response.setMessage("当前物料不是间接物料");
                    return convertJsonString(response);
                }
                callEmptyVehicleRequest.setVehicleType1(goods.getVehicleType());
            }

            // 生成料箱出库任务
            int needNum = callEmptyVehicleRequest.getNeedNum();
            List<Task> vehicleOutTasks = new ArrayList<>();// 任务列表
            List<String> outVehicleIds = new ArrayList<>();// 料箱列表
            // 查询出需求数量的空箱
            List<Vehicle> emptyVehicles = vehicleService.list(new LambdaQueryWrapper<Vehicle>()
                    .eq(StringUtils.isNotEmpty(callEmptyVehicleRequest.getVehicleType1()), Vehicle::getVehicleType, callEmptyVehicleRequest.getVehicleType1())
                    .eq(Vehicle::getIsEmpty, 1)
                    .eq(Vehicle::getVehicleStatus, VehicleStatus.ON.getCode())
                    .orderByAsc(Vehicle::getLastInTime)
                    .last("limit " + needNum));
            for (Vehicle emptyVehicle : emptyVehicles) {
                if (needNum <= 0) {
                    break;
                }
                // 创建一个空箱出库任务
                Task emptyVehicleTask = new Task();
                emptyVehicleTask.setTaskId(generateId("VCK_"));
                emptyVehicleTask.setTaskType(TaskType.OUT.getCode());
                emptyVehicleTask.setTaskStatus(WmsTaskStatus.NEW.getCode());
                emptyVehicleTask.setOrigin(emptyVehicle.getCurrentLocation());
                emptyVehicleTask.setDestination("");
                emptyVehicleTask.setTaskPriority(1);
                emptyVehicleTask.setTaskGroup(generateId(""));
                emptyVehicleTask.setVehicleId(emptyVehicle.getVehicleId());
                emptyVehicleTask.setWeight(BigDecimal.ZERO);
                emptyVehicleTask.setVehicleSize(1);
                emptyVehicleTask.setCreateTime(LocalDateTime.now());
                emptyVehicleTask.setUserName(callEmptyVehicleRequest.getUserName());
                emptyVehicleTask.setIsPicking(0);
                vehicleOutTasks.add(emptyVehicleTask);
                // 出库料箱表
                outVehicleIds.add(emptyVehicle.getVehicleId());
                needNum--;
            }
            // 保存任务
            taskService.saveBatch(vehicleOutTasks);
            // 更新料箱表
            vehicleService.update(new LambdaUpdateWrapper<Vehicle>()
                    .set(Vehicle::getVehicleStatus, VehicleStatus.OUT.getCode())
                    .in(Vehicle::getVehicleId, outVehicleIds)
                    .ne(Vehicle::getVehicleStatus, VehicleStatus.OUT.getCode()));
            if (needNum <= 0) {
                response.setCode(ResponseCode.OK.getCode());
                response.setMessage("呼叫空箱成功，请等待箱子出库。");
            } else if (needNum < callEmptyVehicleRequest.getNeedNum()) {
                response.setCode(ResponseCode.OK.getCode());
                response.setMessage("已呼叫空箱，但库中空箱数量不足。需求" + callEmptyVehicleRequest.getNeedNum() + "个，实际呼叫" + vehicleOutTasks.size() + "个。");
            } else {
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("库中没有空箱了。");
            }
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("呼叫空箱发生异常，{}", convertJsonString(e));
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("呼叫空箱发生异常");
            return convertJsonString(response);
        }
    }

    /**
     * Wcs请求箱子是否回库
     *
     * @param requestBackQuery 请求信息
     * @return 结果
     */
    @PostMapping("/requestBack")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    @MyLog(logTitle = "Wcs请求箱子是否回库", logMethod = "requestBack")
    public String requestBack(@RequestBody RequestBackQuery requestBackQuery) {
        logger.info("Wcs请求箱子是否回库：{}，ip地址：{}", convertJsonString(requestBackQuery), HttpUtils.getIpAddr(servletRequest));
        ResponseEntity response = new ResponseEntity();
        try {
            // 验证数量
            if (StringUtils.isEmpty(requestBackQuery.getVehicleId())) {
                logger.error("缺少箱子号。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("缺少箱子号。");
                return convertJsonString(response);
            }
            // 判断这个箱子是否还有拣选任务
            boolean hasPickTasks = pickTaskService.exists(new LambdaQueryWrapper<PickTask>()
                    .eq(PickTask::getVehicleId, requestBackQuery.getVehicleId()));
            if (!hasPickTasks) {
                // 查询到当前料箱
                Vehicle vehicle = vehicleService.getOne(new LambdaQueryWrapper<Vehicle>()
                        .eq(Vehicle::getVehicleId, requestBackQuery.getVehicleId())
                        .last("limit 1"));
                if (vehicle != null) {
                    if (Objects.equals(vehicle.getVehicleStatus(), VehicleStatus.ON.getCode())) {
                        logger.error("当前箱子{}已在库中，无法回库。", requestBackQuery.getVehicleId());
                        response.setCode(ResponseCode.ERROR.getCode());
                        response.setMessage("当前箱子" + requestBackQuery.getVehicleId() + "已在库中，无法回库。");
                        return convertJsonString(response);
                    }
                    if (Objects.equals(vehicle.getVehicleStatus(), VehicleStatus.EXCEPTION.getCode())) {
                        logger.info("异常箱子，可以离开线体。");
                        response.setCode(ResponseCode.OK.getCode());
                        response.setMessage("异常箱子，可以离开线体。");
                        return convertJsonString(response);
                    }
                } else {
                    // 查询配置
                    String allowEmptyBack = configMap.get(ConfigMapKeyEnum.ALLOW_EMPTY_BACK.getConfigKey());
                    if (StringUtils.isEmpty(allowEmptyBack) || !allowEmptyBack.equals("1")) {
                        logger.error("当前配置不允许新空箱回库。");
                        response.setCode(ResponseCode.ERROR.getCode());
                        response.setMessage("当前配置不允许新空箱回库。");
                        return convertJsonString(response);
                    }
                }
                // 判断当前载具是否有回库任务
                boolean hasBackTask = taskService.exists(new LambdaQueryWrapper<Task>()
                        .eq(Task::getVehicleId, requestBackQuery.getVehicleId())
                        .eq(Task::getTaskType, TaskType.IN.getCode())
                        .likeRight(Task::getTaskId, "HK_"));
                if (!hasBackTask) {
                    // 判断当前载具是否有入库任务
                    List<Task> inTasks = taskService.list(new LambdaQueryWrapper<Task>()
                            .eq(Task::getVehicleId, requestBackQuery.getVehicleId())
                            .eq(Task::getTaskType, TaskType.IN.getCode())
                            .likeRight(Task::getTaskId, "RK_"));
                    if (inTasks != null && !inTasks.isEmpty()) {
                        if (StringUtils.isEmpty(inTasks.get(0).getDestination())) {
                            // 寻找库位
                            String nextLocationId = requestALocation(requestBackQuery.getVehicleId());
                            if (Objects.equals(nextLocationId, "")) {
                                logger.error("暂无可用库位");
                                response.setCode(ResponseCode.ERROR.getCode());
                                response.setMessage("暂无可用库位！");
                                return convertJsonString(response);
                            }
                            if (!taskService.update(new LambdaUpdateWrapper<Task>()
                                    .set(Task::getTaskStatus, WmsTaskStatus.NEW.getCode())
                                    .set(Task::getDestination, nextLocationId)
                                    .eq(Task::getVehicleId, requestBackQuery.getVehicleId())
                                    .eq(Task::getTaskType, TaskType.IN.getCode())
                                    .eq(Task::getTaskStatus, WmsTaskStatus.TEMP.getCode())
                                    .likeRight(Task::getTaskId, "RK_"))) {
                                // 回退库位锁定
                                locationService.update(new LambdaUpdateWrapper<Location>()
                                        .set(Location::getLocationStatus, LocationStatus.EMPTY.getCode())
                                        .set(Location::getVehicleId, "")
                                        .eq(Location::getLocationId, nextLocationId)
                                        .eq(Location::getLocationStatus, LocationStatus.OCCUPY.getCode()));
                                logger.error("更新入库任务失败，箱号：{}", requestBackQuery.getVehicleId());
                                response.setCode(ResponseCode.ERROR.getCode());
                                response.setMessage("更新入库任务失败。");
                                return convertJsonString(response);
                            }
                        } else {
                            taskService.update(new LambdaUpdateWrapper<Task>()
                                    .set(Task::getTaskStatus, WmsTaskStatus.NEW.getCode())
                                    .eq(Task::getVehicleId, requestBackQuery.getVehicleId())
                                    .eq(Task::getTaskType, TaskType.IN.getCode())
                                    .eq(Task::getTaskStatus, WmsTaskStatus.TEMP.getCode())
                                    .likeRight(Task::getTaskId, "RK_"));
                        }
                    } else {
                        // 寻找库位
                        String nextLocationId = requestALocation(requestBackQuery.getVehicleId());
                        if (Objects.equals(nextLocationId, "")) {
                            logger.error("暂无可用库位");
                            response.setCode(ResponseCode.ERROR.getCode());
                            response.setMessage("暂无可用库位！");
                            return convertJsonString(response);
                        }
                        // 生成回库任务
                        Task backTask = new Task();
                        backTask.setTaskId(generateId("HK_"));
                        backTask.setTaskGroup(generateId(""));
                        backTask.setTaskType(TaskType.IN.getCode());
                        backTask.setTaskStatus(WmsTaskStatus.NEW.getCode());
                        backTask.setVehicleId(requestBackQuery.getVehicleId());
                        backTask.setDestination(nextLocationId);
                        backTask.setVehicleSize(1);
                        backTask.setWeight(BigDecimal.ZERO);
                        backTask.setTaskPriority(1);
                        backTask.setUserName("WMS");
                        backTask.setCreateTime(LocalDateTime.now());
                        if (taskService.save(backTask)) {
                            // 删除outsideVehicle表
                            outsideVehiclesService.remove(new LambdaQueryWrapper<OutsideVehicles>().eq(OutsideVehicles::getVehicleId, requestBackQuery.getVehicleId()));
                            // 设置库存状态为回库中
                            stockService.update(new LambdaUpdateWrapper<Stock>()
                                    .set(Stock::getStockStatus, StockStatus.BACK.getCode())
                                    .eq(Stock::getVehicleId, requestBackQuery.getVehicleId()));
                        } else {
                            // 回退库位锁定
                            locationService.update(new LambdaUpdateWrapper<Location>()
                                    .set(Location::getLocationStatus, LocationStatus.EMPTY.getCode())
                                    .set(Location::getVehicleId, "")
                                    .eq(Location::getLocationId, nextLocationId)
                                    .eq(Location::getLocationStatus, LocationStatus.OCCUPY.getCode()));
                            logger.error("生成回库任务失败，箱号：{}", requestBackQuery.getVehicleId());
                            response.setCode(ResponseCode.ERROR.getCode());
                            response.setMessage("生成回库任务失败。");
                            return convertJsonString(response);
                        }
                    }
                }
                response.setCode(ResponseCode.OK.getCode());
                response.setMessage("可以回库。");
            } else {
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("不可以回库。");
            }
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("处理回库请求异常，{}", convertJsonString(e));
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("处理回库请求异常：" + e.getMessage());
            return convertJsonString(response);
        }
    }

    public String requestALocation(String vehicleId) {
        String nextLocationId = "";
        int emptyLocationSize = (int) locationService.count(new LambdaQueryWrapper<Location>().eq(Location::getLocationStatus, LocationStatus.EMPTY.getCode()));
        for (int i = 0; i < emptyLocationSize; i++) {
            Map<String, String> resultMap = locationService.getOneLocation("", "");
            if (resultMap.isEmpty() || !resultMap.containsKey("nextLocationId")) {
                return "";
            } else {
                Location nextLocation = locationService.getOne(new LambdaQueryWrapper<Location>().eq(Location::getLocationId, resultMap.get("nextLocationId")).last("limit 1"));
                LambdaUpdateWrapper<Location> updateLocationWrapper = new LambdaUpdateWrapper<Location>()
                        .set(Location::getLocationStatus, LocationStatus.OCCUPY.getCode())
                        .set(Location::getVehicleId, vehicleId)
                        .eq(Location::getLocationId, nextLocation.getLocationId())
                        .eq(Location::getLocationStatus, LocationStatus.EMPTY.getCode());
                if (locationService.update(updateLocationWrapper)) {
                    nextLocationId = resultMap.get("nextLocationId");
                    break;
                }
            }
        }
        return nextLocationId;
    }

    /**
     * 请求打印标签的数据
     *
     * @param printRequest 请求信息
     * @return 结果
     */
    @PostMapping("/requestPrintData")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    @MyLog(logTitle = "请求打印标签的数据", logMethod = "requestPrintData")
    public String requestPrintData(@RequestBody PrintRequest printRequest) {
        logger.info("请求打印标签的数据：{}，ip地址：{}", convertJsonString(printRequest), HttpUtils.getIpAddr(servletRequest));
        ResponseEntity response = new ResponseEntity();
        try {
            // 获取站台号
            String standId = "";
            if (StringUtils.isNotEmpty(printRequest.getStandId())) {
                // 站台号从请求参数中获取
                standId = printRequest.getStandId();
            } else {
                // 站台号从ip获取
                Stand standOfIp = standService.getOne(new LambdaQueryWrapper<Stand>()
                        .eq(Stand::getStandIp, HttpUtils.getIpAddr(servletRequest))
                        .eq(Stand::getStandType, 2)
                        .last("limit 1"));
                if (standOfIp != null && StringUtils.isNotEmpty(standOfIp.getStandId())) {
                    standId = standOfIp.getStandId();
                }
            }
            if (StringUtils.isEmpty(standId)) {
                logger.error("请求参数缺少站台号。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("请求参数缺少站台号。");
                return convertJsonString(response);
            }
            // 根据站台号查找电子标签配置表
            List<ELocationConfig> eLocationConfigs = eLocationConfigService.list(new LambdaQueryWrapper<ELocationConfig>()
                    .eq(ELocationConfig::getWorkStation, standId));
            if (eLocationConfigs == null || eLocationConfigs.isEmpty()) {
                logger.error("没有可以打印的标签。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("没有可以打印的标签。");
                return convertJsonString(response);
            }
            List<BoxPrintData> boxPrintDatas = new ArrayList<>();
            for (ELocationConfig eLocationConfig : eLocationConfigs) {
                BoxPrintData boxPrintData = new BoxPrintData();
                // 查找电子标签库位
                ETagLocation eTagLocation = etagLocationService.getOne(new LambdaQueryWrapper<ETagLocation>()
                        .eq(ETagLocation::getELocationId, eLocationConfig.getELocationId())
                        .last("limit 1"));
                // 获取工作流信息
                List<WorkFlow> workFlows = workFlowService.list(new LambdaQueryWrapper<WorkFlow>()
                        .eq(WorkFlow::getWorkOrder, eLocationConfig.getWorkOrder())
                        .eq(WorkFlow::getWorkCenter, eLocationConfig.getWorkCenter())
                        .eq(WorkFlow::getWorkStation, eLocationConfig.getWorkStation()));
                // 查询DBS
                KateDBS kateDBS = kateDBSService.getOne(new LambdaQueryWrapper<KateDBS>()
                        .eq(KateDBS::getWorkOrder, eLocationConfig.getWorkOrder())
                        .last("limit 1"));
                if (eTagLocation == null || workFlows == null || workFlows.isEmpty() || kateDBS == null) {
                    // 存在数据异常，跳过
                    continue;
                }
                // 开始设定标签信息
                boxPrintData.setSequenceNo(eTagLocation.getSequenceId());
                boxPrintData.setMachineNo(kateDBS.getMachineNo());
                boxPrintData.setSmallWorkCenter(eLocationConfig.getWorkCenter());
                boxPrintData.setWorkOrder(eLocationConfig.getWorkOrder());
                boxPrintData.setGoodsCount(workFlows.stream().map(WorkFlow::getGoodsId).distinct().toList().size());
                boxPrintData.setGoodsNumCount(workFlows.stream().map(WorkFlow::getPickedNum).reduce(BigDecimal.ZERO, BigDecimal::add));
                boxPrintData.setOpTime(workFlows.get(0).getFinishTime());
                boxPrintData.setOpUser(workFlows.get(0).getOpUser());
                boxPrintDatas.add(boxPrintData);
                // 设置打印状态
                eLocationConfig.setPrintStatus(1);
                eLocationConfig.setPrintCounts(eLocationConfig.getPrintCounts() + 1);
            }
            // 更新电子标签库位
            eLocationConfigService.updateBatchById(eLocationConfigs);

            logger.info("获取打印标签成功。");
            response.setCode(ResponseCode.OK.getCode());
            response.setMessage("获取打印标签成功。");
            response.setReturnData(boxPrintDatas);
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("获取打印标签异常，{}", convertJsonString(e));
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("获取打印标签异常。");
            return convertJsonString(response);
        }
    }

    /**
     * 请求当前大盒子个数
     *
     * @param sortBoxRequest 请求信息
     * @return 结果
     */
    @PostMapping("/requestSumOfBox")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    @MyLog(logTitle = "获取大盒子数量", logMethod = "requestSumOfBox")
    public String requestSumOfBox(@RequestBody SortBoxRequest sortBoxRequest) {
        logger.info("获取大盒子数量：{}，ip地址：{}", convertJsonString(sortBoxRequest), HttpUtils.getIpAddr(servletRequest));
        ResponseEntity response = new ResponseEntity();
        try {
            // 判断请求参数是否正确
            if (sortBoxRequest == null || StringUtils.isEmpty(sortBoxRequest.getBigBoxNo())) {
                logger.error("请求参数缺少大盒子号。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("请求参数缺少大盒子号。");
                return convertJsonString(response);
            }
            // 获取站台号
            String standId = "";
            if (StringUtils.isNotEmpty(sortBoxRequest.getStandId())) {
                // 站台号从请求参数中获取
                standId = sortBoxRequest.getStandId();
            } else {
                // 站台号从ip获取
                Stand standOfIp = standService.getOne(new LambdaQueryWrapper<Stand>()
                        .eq(Stand::getStandIp, HttpUtils.getIpAddr(servletRequest))
                        .eq(Stand::getStandType, 2)
                        .last("limit 1"));
                if (standOfIp != null && StringUtils.isNotEmpty(standOfIp.getStandId())) {
                    standId = standOfIp.getStandId();
                }
            }
            if (StringUtils.isEmpty(standId)) {
                logger.error("请求参数缺少站台号。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("请求参数缺少站台号。");
                return convertJsonString(response);
            }
            // 判断大盒子号是否正确
            List<WorkStationConfig> stationConfigs = workStationConfigService.list(new LambdaQueryWrapper<WorkStationConfig>()
                    .eq(WorkStationConfig::getBigBox, sortBoxRequest.getBigBoxNo())
                    .eq(WorkStationConfig::getWorkStation, standId));
            if (stationConfigs == null || stationConfigs.isEmpty()) {
                logger.error("请输入正确的大盒子号。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("请输入正确的大盒子号。");
                return convertJsonString(response);
            }
            // 当前要亮灯的大盒子
            WorkStationConfig currentBigBoxConfig = stationConfigs.get(0);
            // 当前配置的工单数/大盒子
            int orderQuantity = currentBigBoxConfig.getOrderQuantity();
            // 查询这个大盒子对应的小盒子
            List<String> smallBoxListOfAll = stationConfigs.stream().map(WorkStationConfig::getSmallBox).distinct().toList();
            // 找出本次工作中的标签位
            List<ELocationConfigLast> eConfigLastList = eLocationConfigLastService.list(new LambdaQueryWrapper<ELocationConfigLast>()
                    .eq(ELocationConfigLast::getWorkStation, standId)
                    .in(ELocationConfigLast::getWorkCenter, smallBoxListOfAll));
            if (eConfigLastList.isEmpty()) {
                logger.error("当前大盒子暂时不需要亮灯。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("当前大盒子暂时不需要亮灯。");
                return convertJsonString(response);
            }
            if (orderQuantity <= 0) {
                sortBoxRequest.setSumOfOrders(0);
            } else {
                // 根据这些小盒子号找到对应的工单
                List<String> orderIds = eConfigLastList.stream().map(ELocationConfigLast::getWorkOrder).distinct().toList();
                sortBoxRequest.setSumOfOrders((orderIds.size() + orderQuantity - 1) / orderQuantity);
            }

            response.setCode(ResponseCode.OK.getCode());
            response.setMessage("获取大盒子数量成功。");
            response.setReturnData(sortBoxRequest);
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("处理整理盒子请求异常，{}", convertJsonString(e));
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("处理整理盒子请求异常。");
            return convertJsonString(response);
        }
    }

    /**
     * 请求整理盒子
     *
     * @param sortBoxRequest 请求信息
     * @return 结果
     */
    @PostMapping("/requestSortBox")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    @MyLog(logTitle = "请求整理盒子", logMethod = "requestSortBox")
    public String requestSortBox(@RequestBody SortBoxRequest sortBoxRequest) {
        logger.info("请求整理盒子：{}，ip地址：{}", convertJsonString(sortBoxRequest), HttpUtils.getIpAddr(servletRequest));
        ResponseEntity response = new ResponseEntity();
        try {
            // 判断请求参数是否正确
            if (sortBoxRequest == null || StringUtils.isEmpty(sortBoxRequest.getBigBoxNo())) {
                logger.error("请求参数不全。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("请求参数不全。");
                return convertJsonString(response);
            }
            // 获取站台号
            String standId = "";
            if (StringUtils.isNotEmpty(sortBoxRequest.getStandId())) {
                // 站台号从请求参数中获取
                standId = sortBoxRequest.getStandId();
            } else {
                // 站台号从ip获取
                Stand standOfIp = standService.getOne(new LambdaQueryWrapper<Stand>()
                        .eq(Stand::getStandIp, HttpUtils.getIpAddr(servletRequest))
                        .eq(Stand::getStandType, 2)
                        .last("limit 1"));
                if (standOfIp != null && StringUtils.isNotEmpty(standOfIp.getStandId())) {
                    standId = standOfIp.getStandId();
                }
            }
            if (StringUtils.isEmpty(standId)) {
                logger.error("请求参数缺少站台号。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("请求参数缺少站台号。");
                return convertJsonString(response);
            }
            // 查找对应的标签配置
            List<ELocationConfigLast> lightingBoxList = eLocationConfigLastService.list(new LambdaQueryWrapper<ELocationConfigLast>()
                    .eq(ELocationConfigLast::getWorkStation, standId)
                    .eq(ELocationConfigLast::getBoxStatus, 1));
            if (lightingBoxList != null && !lightingBoxList.isEmpty()) {
                logger.error("请将已亮灯的盒子取走并灭灯后重试。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("请将已亮灯的盒子取走并灭灯后重试。");
                return convertJsonString(response);
            }
            // 判断大盒子号是否正确
            List<WorkStationConfig> stationConfigs = workStationConfigService.list(new LambdaQueryWrapper<WorkStationConfig>()
                    .eq(WorkStationConfig::getBigBox, sortBoxRequest.getBigBoxNo())
                    .eq(WorkStationConfig::getWorkStation, standId));
            if (stationConfigs == null || stationConfigs.isEmpty()) {
                logger.error("请输入正确的大盒子号。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("请输入正确的大盒子号。");
                return convertJsonString(response);
            }
            // 当前要亮灯的大盒子
            WorkStationConfig currentBigBoxConfig = stationConfigs.get(0);
            // 当前配置的工单数/大盒子
            int orderQuantity = currentBigBoxConfig.getOrderQuantity();
            // 亮灯列表
            List<ETaskData> eTaskDataList = new ArrayList<>();
            // 查询这个大盒子对应的小盒子
            List<String> smallBoxListOfAll = stationConfigs.stream().map(WorkStationConfig::getSmallBox).distinct().toList();
            // 找出本次工作中的标签位
            List<ELocationConfigLast> eConfigLastList = eLocationConfigLastService.list(new LambdaQueryWrapper<ELocationConfigLast>()
                    .eq(ELocationConfigLast::getWorkStation, standId)
                    .in(ELocationConfigLast::getWorkCenter, smallBoxListOfAll));
            if (eConfigLastList == null || eConfigLastList.isEmpty()) {
                logger.error("当前大盒子暂时不需要亮灯。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("当前大盒子暂时不需要亮灯。");
                return convertJsonString(response);
            }
            if (orderQuantity <= 0) {
                // 生成亮灯数据
                for (ELocationConfigLast eConfigLast : eConfigLastList) {
                    if (eConfigLast.getBoxStatus() != 0) {
                        // 不是未亮灯的状态
                        continue;
                    }
                    // 当次拣选数量
                    ETaskData eTaskData = new ETaskData();
                    eTaskData.setTaskId(generateId(eConfigLast.getOrderBoxNo() + "_"));// 用户查询对应的拣选任务
                    eTaskData.setETaskId(generateId(eConfigLast.getOrderBoxNo() + "_"));
                    eTaskData.setGoodsId(eConfigLast.getOrderBoxNo());
                    eTaskData.setGoodsName("");
                    eTaskData.setNeedNum(1);
                    eTaskData.setLocation(eConfigLast.getELocationId());
                    eTaskDataList.add(eTaskData);
                    // 更新电子标签库位信息
                    etagLocationService.update(new LambdaUpdateWrapper<ETagLocation>()
                            .set(ETagLocation::getTaskId, eTaskData.getTaskId())
                            .set(ETagLocation::getNeedNum, eTaskData.getNeedNum())
                            .set(ETagLocation::getConfirmNum, eTaskData.getNeedNum())
                            .eq(ETagLocation::getELocationId, eConfigLast.getELocationId()));
                }
            } else {
                if (sortBoxRequest.getOrderOfOrders() == null || sortBoxRequest.getOrderOfOrders() <= 0) {
                    logger.error("请填入正确的盒子序号。");
                    response.setCode(ResponseCode.ERROR.getCode());
                    response.setMessage("请填入正确的盒子序号。");
                    return convertJsonString(response);
                }
                // 查找到所有的工单
                List<String> orderIds = eConfigLastList.stream().map(ELocationConfigLast::getWorkOrder).distinct().toList();
                // 利用DBS对这些工单id进行排序
                List<KateDBS> kateDBSList = kateDBSService.list(new LambdaQueryWrapper<KateDBS>()
                        .in(KateDBS::getWorkOrder, orderIds)
                        .orderByAsc(KateDBS::getWorkSequence));
                if (kateDBSList == null || kateDBSList.isEmpty()) {
                    logger.error("DBS查询错误，请检查DBS清单数据。");
                    response.setCode(ResponseCode.ERROR.getCode());
                    response.setMessage("DBS查询错误，请检查DBS清单数据。");
                    return convertJsonString(response);
                }
                // 查询到这些工单的dbs
                List<String> orderedOrdersIds = kateDBSList.stream().map(KateDBS::getWorkOrder).distinct().toList();
                List<String> toBeLightedOrders = orderedOrdersIds.stream().skip((long) (sortBoxRequest.getOrderOfOrders() - 1) * orderQuantity).limit(orderQuantity).toList();
                // 生成亮灯数据
                if (!toBeLightedOrders.isEmpty()) {
                    for (ELocationConfigLast eConfigLast : eConfigLastList) {
                        if (eConfigLast.getBoxStatus() != 0 || !toBeLightedOrders.contains(eConfigLast.getWorkOrder())) {
                            // 不是未亮灯的状态或者不是这次要亮灯的工单
                            continue;
                        }
                        // 当次拣选数量
                        ETaskData eTaskData = new ETaskData();
                        eTaskData.setTaskId(generateId(eConfigLast.getOrderBoxNo() + "_"));// 用户查询对应的拣选任务
                        eTaskData.setETaskId(generateId(eConfigLast.getOrderBoxNo() + "_"));
                        eTaskData.setGoodsId(eConfigLast.getOrderBoxNo());
                        eTaskData.setGoodsName("");
                        eTaskData.setNeedNum(1);
                        eTaskData.setLocation(eConfigLast.getELocationId());
                        eTaskDataList.add(eTaskData);
                        // 更新电子标签库位信息
                        etagLocationService.update(new LambdaUpdateWrapper<ETagLocation>()
                                .set(ETagLocation::getTaskId, eTaskData.getTaskId())
                                .set(ETagLocation::getNeedNum, eTaskData.getNeedNum())
                                .set(ETagLocation::getConfirmNum, eTaskData.getNeedNum())
                                .eq(ETagLocation::getELocationId, eConfigLast.getELocationId()));
                    }
                }
            }
            if (!eTaskDataList.isEmpty()) {
                // 发送亮灯
                WcsETaskRequest wcsETaskRequest = new WcsETaskRequest();
                wcsETaskRequest.setTaskGroup(generateId(sortBoxRequest.getBigBoxNo() + "_"));
                wcsETaskRequest.setTaskType(2);
                wcsETaskRequest.setTaskData(eTaskDataList);
                wcsETaskRequest.setOrderId(generateId(""));
                wcsETaskRequest.setVehicleNo(sortBoxRequest.getBigBoxNo());
                String sendToWcsETaskUrl = configMap.get(ConfigMapKeyEnum.URL_WCS_E_TASK.getConfigKey());
                if (StringUtils.isEmpty(sendToWcsETaskUrl)) {
                    // url地址为空
                    logger.error("向Wcs发送电子标签亮灯任务的地址为空");
                } else {
                    logger.info("发送电子标签亮灯请求：{}", convertJsonString(wcsETaskRequest));
                    ResponseEntity result = JSON.parseObject(HttpUtils.sendHttpPostWithoutToken(sendToWcsETaskUrl, convertJsonString(wcsETaskRequest)), ResponseEntity.class);
                    try {
                        logService.save(new WmsLog(WmsUtils.generateId("LOG_"), "发送电子标签任务", "eTagTask", convertJsonString(wcsETaskRequest), convertJsonString(result), sendToWcsETaskUrl, LocalDateTime.now(), "WMS"));
                    } catch (Exception e) {
                        logger.error("插入日志错误");
                    }
                    if (result == null || !Objects.equals(result.getCode(), ResponseCode.OK.getCode())) {
                        logger.error("发送电子标签亮灯任务失败：{}", convertJsonString(result));
                        throw new Exception("发送电子标签亮灯任务失败。");
                    } else {
                        // 更新亮灯数据
                        etagLocationService.update(new LambdaUpdateWrapper<ETagLocation>()
                                .set(ETagLocation::getPickStatus, 1)
                                .set(ETagLocation::getTaskType, wcsETaskRequest.getTaskType())
                                .set(ETagLocation::getVehicleNo, wcsETaskRequest.getVehicleNo())
                                .in(ETagLocation::getELocationId, eTaskDataList.stream().map(ETaskData::getLocation).collect(Collectors.toList())));
                    }
                }
                logger.info("处理整理盒子请求成功。");
                response.setCode(ResponseCode.OK.getCode());
                response.setMessage("请根据灯光拣选盒子。");
                response.setReturnData(sortBoxRequest);
            } else {
                logger.info("没有可亮灯的数据或者灯光已经全部亮过。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("没有可亮灯的数据或者灯光已经全部亮过。");
            }
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("处理整理盒子请求异常，{}", convertJsonString(e));
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("处理整理盒子请求异常：" + e.getMessage());
            return convertJsonString(response);
        }
    }

    /**
     * 直接物料非计划领料
     *
     * @param noPlanRequest 请求信息
     * @return 结果
     */
    @PostMapping("/clcNoPlan")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    @MyLog(logTitle = "直接物料非计划领料", logMethod = "clcNoPlan")
    public String clcNoPlan(@RequestBody NoPlanRequest noPlanRequest) {
        logger.info("直接物料非计划领料：{}，ip地址：{}", convertJsonString(noPlanRequest), HttpUtils.getIpAddr(servletRequest));
        ResponseEntity response = new ResponseEntity();
        try {
            if (StringUtils.isEmpty(noPlanRequest.getGoodsId())
                    || noPlanRequest.getNeedNum() == null || noPlanRequest.getNeedNum().compareTo(BigDecimal.ZERO) <= 0) {
                logger.error("非计划领料，请输入料号和数量。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("非计划领料，请输入料号和数量。");
                return convertJsonString(response);
            }
            // 获取站台号
            Stand targetStand;
            if (StringUtils.isNotEmpty(noPlanRequest.getStandId())) {
                // 站台号从请求参数中获取
                targetStand = standService.getById(noPlanRequest.getStandId());
            } else {
                // 站台号从ip获取
                targetStand = standService.getOne(new LambdaQueryWrapper<Stand>()
                        .eq(Stand::getStandIp, HttpUtils.getIpAddr(servletRequest))
                        .eq(Stand::getStandType, 1)
                        .last("limit 1"));
            }
            if (targetStand == null) {
                logger.error("查询拣选站台错误。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("查询拣选站台错误。");
                return convertJsonString(response);
            }
            // 查询库存
            List<Stock> stockList = stockService.list(new LambdaQueryWrapper<Stock>()
                    .apply("goods_related ->> '$.goodsId' = {0}" + MYSQL_JSON_CI, noPlanRequest.getGoodsId())
                    .apply("goods_related ->> '$.remainNum' > 0")
                    .orderByAsc(Stock::getCreateTime));
            // 查询应该的库存总数
            List<StockOfGoodsDto> stockOfGoodsList = stockService.selectSumOfGoods(noPlanRequest.getGoodsId());
            // 总数量
            BigDecimal stockNum = stockOfGoodsList.stream().map(StockOfGoodsDto::getRemainNumSum).reduce(BigDecimal.ZERO, BigDecimal::add);
            if (stockList != null && !stockList.isEmpty()) {
                // 需求数量
                BigDecimal needNum = noPlanRequest.getNeedNum();
                // 出库任务列表
                List<Task> outTasks = new ArrayList<>();
                // 尝试生成出库任务
                List<String> pickStandIds = new ArrayList<>();
                for (Stock tempStock : stockList) {
                    if (needNum.compareTo(BigDecimal.ZERO) <= 0) {// 需求数量小于等于0
                        break;
                    }
                    if (Objects.equals(tempStock.getStockStatus(), StockStatus.OK.getCode())) {
                        if (tempStock.getGoodsRelated().getRemainNum().compareTo(needNum) > 0) {
                            // 当前箱子剩余物料数量多于需求数量
                            needNum = BigDecimal.ZERO;
                            // 设置剩余数量
                            StockDetailInfo goodsRelated = tempStock.getGoodsRelated();
                            goodsRelated.setRemainNum(goodsRelated.getRemainNum().subtract(needNum));
                            tempStock.setGoodsRelated(goodsRelated);
                        } else {
                            // 当前箱子物料剩余数量少于需求数量
                            needNum = needNum.subtract(tempStock.getGoodsRelated().getRemainNum());
                            // 设置剩余数量
                            StockDetailInfo goodsRelated = tempStock.getGoodsRelated();
                            goodsRelated.setRemainNum(BigDecimal.ZERO);
                            tempStock.setGoodsRelated(goodsRelated);
                        }
                        // 创建出库任务
                        Task tempOutTask = new Task();
                        tempOutTask.setTaskId(generateId("CK_"));
                        tempOutTask.setTaskType(TaskType.OUT.getCode());
                        tempOutTask.setTaskGroup(generateId(""));
                        tempOutTask.setTaskStatus(WmsTaskStatus.NEW.getCode());
                        tempOutTask.setTaskPriority(2);
                        tempOutTask.setVehicleId(tempStock.getVehicleId());
                        tempOutTask.setUserName(noPlanRequest.getUserName());
                        tempOutTask.setOrigin(tempStock.getLocationId());
                        tempOutTask.setDestination("");
                        tempOutTask.setCreateTime(LocalDateTime.now());
                        tempOutTask.setIsPicking(1);
                        outTasks.add(tempOutTask);
                    } else if (Objects.equals(tempStock.getStockStatus(), StockStatus.OUT.getCode())
                            || Objects.equals(tempStock.getStockStatus(), StockStatus.PICKING.getCode())) {
                        // 查询这个箱子的拣选任务
                        List<PickTask> thisVehiclePickTasks = pickTaskService.list(new LambdaQueryWrapper<PickTask>()
                                .eq(PickTask::getVehicleId, tempStock.getVehicleId()));
                        if (thisVehiclePickTasks.isEmpty()) {
                            if (tempStock.getGoodsRelated().getRemainNum().compareTo(needNum) > 0) {
                                // 当前箱子剩余物料数量多于需求数量
                                needNum = BigDecimal.ZERO;
                                // 设置剩余数量
                                StockDetailInfo goodsRelated = tempStock.getGoodsRelated();
                                goodsRelated.setRemainNum(goodsRelated.getRemainNum().subtract(needNum));
                                tempStock.setGoodsRelated(goodsRelated);
                            } else {
                                // 当前箱子物料剩余数量少于需求数量
                                needNum = needNum.subtract(tempStock.getGoodsRelated().getRemainNum());
                                // 设置剩余数量
                                StockDetailInfo goodsRelated = tempStock.getGoodsRelated();
                                goodsRelated.setRemainNum(BigDecimal.ZERO);
                                tempStock.setGoodsRelated(goodsRelated);
                            }
                        } else {
                            // 将这个箱子对应的出库任务优先级设置位2
                            taskService.update(new LambdaUpdateWrapper<Task>()
                                    .set(Task::getTaskPriority, 2)
                                    .eq(Task::getVehicleId, tempStock.getVehicleId())
                                    .eq(Task::getTaskStatus, WmsTaskStatus.NEW.getCode()));
                            thisVehiclePickTasks.forEach(pickTask -> {
                                if (!pickStandIds.contains(pickTask.getStandId())) {
                                    pickStandIds.add(pickTask.getStandId());
                                }
                            });
                        }
                    }
                }
                // 添加出库任务
                if (!outTasks.isEmpty()) {
                    taskService.saveBatch(outTasks);
                    List<String> vehicleIds = outTasks.stream().map(Task::getVehicleId).distinct().toList();
                    // 更新库存状态
                    stockService.update(new LambdaUpdateWrapper<Stock>()
                            .set(Stock::getStockStatus, StockStatus.OUT.getCode())
                            .in(Stock::getVehicleId, vehicleIds)
                            .eq(Stock::getStockStatus, StockStatus.OK.getCode()));
                    // 更新料箱状态
                    vehicleService.update(new LambdaUpdateWrapper<Vehicle>()
                            .set(Vehicle::getVehicleStatus, VehicleStatus.OUT.getCode())
                            .in(Vehicle::getVehicleId, vehicleIds)
                            .eq(Vehicle::getVehicleStatus, VehicleStatus.ON.getCode()));
                }
                // 非计划领料记录生成
                NoPlanRecord noPlanRecord = new NoPlanRecord();
                noPlanRecord.setRecordId(generateId("CLC-NO-PLAN_"));
                noPlanRecord.setCallType(1);
                noPlanRecord.setGoodsId(noPlanRequest.getGoodsId());
                noPlanRecord.setNeedNum(noPlanRequest.getNeedNum());
                noPlanRecord.setStockNum(stockNum);
                noPlanRecord.setWorkOrder(noPlanRequest.getWorkOrder());
                noPlanRecord.setSmallVehicleNo(noPlanRequest.getSmallVehicleNo());
                noPlanRecord.setCallReason(noPlanRequest.getCallReason());
                noPlanRecord.setFlowNo(noPlanRequest.getFlowNo());
                noPlanRecord.setRemark(noPlanRequest.getRemark());
                noPlanRecord.setCallTime(LocalDateTime.now());
                noPlanRecord.setCallUser(noPlanRequest.getCallUser());
                noPlanRecord.setPickedNum(BigDecimal.ZERO);
                noPlanRecord.setPickStatus(0);// 未拣选
                noPlanRecordService.save(noPlanRecord);

                logger.info("处理直接物料非计划领料请求成功。");
                response.setCode(ResponseCode.OK.getCode());
                StringBuilder message = new StringBuilder("处理直接物料非计划领料请求成功。");
                if (!pickStandIds.isEmpty()) {
                    message.append("有料需要去工作站台领取。站台号：");
                    pickStandIds.forEach(pickStandId -> message.append(pickStandId).append("、"));
                    message.replace(message.length() - 1, message.length(), "。");
                }
                response.setMessage(String.valueOf(message));
            } else {
                logger.error("非计划领料没有库存。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("非计划领料没有库存。");
            }
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("处理直接物料非计划领料请求异常，{}", convertJsonString(e));
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("处理直接物料非计划领料请求异常。");
            return convertJsonString(response);
        }
    }

    /**
     * 获取当前物料的待领料数量
     *
     * @param pickNumQuery 请求信息
     * @return 结果
     */
    @PostMapping("/getCurrentGoodsPickNum")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    @MyLog(logTitle = "获取当前物料的待领料数量", logMethod = "getCurrentGoodsPickNum")
    public String getCurrentGoodsPickNum(@RequestBody PickNumQuery pickNumQuery) {
        logger.info("获取当前物料的待领料数量：{}，ip地址：{}", convertJsonString(pickNumQuery), HttpUtils.getIpAddr(servletRequest));
        ResponseEntity response = new ResponseEntity();
        try {

            logger.info("获取当前物料的待领料数量成功。");
            response.setCode(ResponseCode.OK.getCode());
            response.setMessage("获取当前物料的待领料数量成功。");
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("获取当前物料的待领料数量异常，{}", convertJsonString(e));
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("获取当前物料的待领料数量异常。");
            return convertJsonString(response);
        }
    }

    /**
     * 直接物料非计划领料确认回库
     *
     * @param pickNumQuery 请求信息
     * @return 结果
     */
    @PostMapping("/clcNoPlanConfirmBack")
    @ResponseBody
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    @MyLog(logTitle = "直接物料非计划领料确认回库", logMethod = "clcNoPlanConfirmBack")
    public String clcNoPlanConfirmBack(@RequestBody PickNumQuery pickNumQuery) {
        logger.info("直接物料非计划领料确认回库：{}，ip地址：{}", convertJsonString(pickNumQuery), HttpUtils.getIpAddr(servletRequest));
        ResponseEntity response = new ResponseEntity();
        try {
            // 判断信息是否完备
            if (StringUtils.isEmpty(pickNumQuery.getGoodsId())
                    || StringUtils.isEmpty(pickNumQuery.getVehicleId())
                    || pickNumQuery.getRealPickNum() == null) {
                logger.error("请求缺少必须参数，箱号、料号、数量不可缺少。");
                response.setCode(ResponseCode.OK.getCode());
                response.setMessage("请求缺少必须参数，箱号、料号、数量不可缺少。");
                return convertJsonString(response);
            }
            // 验证载具号是否重复入库
            if (vehicleService.exists(new LambdaQueryWrapper<Vehicle>().eq(Vehicle::getVehicleId, pickNumQuery.getVehicleId())
                    .and(wrapper -> wrapper.eq(Vehicle::getVehicleStatus, VehicleStatus.ON.getCode())))) {
                logger.error("当前箱子{}已在库中，无法回库。", pickNumQuery.getVehicleId());
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("当前箱子" + pickNumQuery.getVehicleId() + "已在库中，无法回库。");
                return convertJsonString(response);
            }
            // 更新库存
            Stock existStock = stockService.getOne(new LambdaQueryWrapper<Stock>()
                    .apply("goods_related ->> '$.goodsId' = {0}" + MYSQL_JSON_CI, pickNumQuery.getGoodsId())
                    .eq(Stock::getVehicleId, pickNumQuery.getVehicleId())
                    .last("limit 1"));
            // 更新库存数量
            if (existStock != null && existStock.getGoodsRelated() != null) {
                Stock originStock = BeanUtil.copyProperties(existStock, Stock.class);
                BigDecimal quantityBefore = originStock.getGoodsRelated().getRemainNum();
                StockDetailInfo goodsDetail = existStock.getGoodsRelated();
                // 设置剩余库存
                if (pickNumQuery.getRemainNum() != null) {
                    goodsDetail.setRemainNum(pickNumQuery.getRemainNum());
                } else {
                    BigDecimal calRemainNum = goodsDetail.getRemainNum().subtract(pickNumQuery.getRealPickNum());
                    if (calRemainNum.compareTo(BigDecimal.ZERO) <= 0) {
                        logger.error("系统计算领料后库存为0，请界面输入剩余数量后再确认回库。");
                        response.setCode(ResponseCode.ERROR.getCode());
                        response.setMessage("系统计算领料后库存为0，请界面输入剩余数量后再确认回库。");
                        return convertJsonString(response);
                    } else {
                        goodsDetail.setRemainNum(calRemainNum);
                    }
                }
                existStock.setGoodsRelated(goodsDetail);
                stockService.updateById(existStock);
                stockUpdateRecordService.addStockUpdateRecord(originStock, existStock, StockUpdateReasonEnum.CLC_NO_PLAN_UPDATE.getReason(), pickNumQuery.getUserName(), quantityBefore);
            }
            // 判断这个箱子是否还有拣选任务
            boolean hasPickTasks = pickTaskService.exists(new LambdaQueryWrapper<PickTask>()
                    .eq(PickTask::getVehicleId, pickNumQuery.getVehicleId()));
            if (!hasPickTasks) {
                // 判断当前载具是否有回库任务
                boolean hasBackTask = taskService.exists(new LambdaQueryWrapper<Task>()
                        .eq(Task::getVehicleId, pickNumQuery.getVehicleId())
                        .eq(Task::getTaskType, TaskType.IN.getCode())
                        .likeRight(Task::getTaskId, "HK_"));
                if (!hasBackTask) {
                    // 判断当前载具是否有入库任务
                    boolean hasInTask = taskService.exists(new LambdaQueryWrapper<Task>()
                            .eq(Task::getVehicleId, pickNumQuery.getVehicleId())
                            .eq(Task::getTaskType, TaskType.IN.getCode())
                            .eq(Task::getTaskStatus, WmsTaskStatus.TEMP.getCode())
                            .likeRight(Task::getTaskId, "RK_"));
                    if (!hasInTask) {
                        // 生成回库任务
                        Task backTask = new Task();
                        backTask.setTaskId(generateId("HK_"));
                        backTask.setTaskGroup(generateId(""));
                        backTask.setTaskType(TaskType.IN.getCode());
                        backTask.setTaskStatus(WmsTaskStatus.TEMP.getCode());
                        backTask.setVehicleId(pickNumQuery.getVehicleId());
                        backTask.setVehicleSize(1);
                        backTask.setWeight(BigDecimal.ZERO);
                        backTask.setTaskPriority(1);
                        backTask.setUserName(pickNumQuery.getUserName());
                        backTask.setCreateTime(LocalDateTime.now());
                        taskService.save(backTask);
                    }
                }
                logger.info("确认回库成功。");
                response.setCode(ResponseCode.OK.getCode());
                response.setMessage("确认回库成功。");
            } else {
                logger.error("当前箱子还有拣选任务，不能回库，请将箱子置入拣货环线。");
                response.setCode(ResponseCode.ERROR.getCode());
                response.setMessage("当前箱子还有拣选任务，不能回库，请将箱子置入拣货环线。");
            }
            return convertJsonString(response);
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("处理确认回库请求异常，{}", convertJsonString(e));
            response.setCode(ResponseCode.ERROR.getCode());
            response.setMessage("处理确认回库请求异常。");
            return convertJsonString(response);
        }
    }
}