chengsc
2025-06-11 1c2541b283ce6ba855e67c476412dffe2c693480
Wms/WMS.BLL/BllSoServer/ExportNoticeServer.cs
@@ -26,12 +26,17 @@
using System.Runtime.Intrinsics.X86;
using ZXing.OneD;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Drawing.Drawing2D;
using Model.ModelDto.LogDto;
using AutoMapper.Internal;
namespace WMS.BLL.BllSoServer
{
    public class ExportNoticeServer : DbHelper<BllExportNotice>, IExportNoticeServer
    {
        private static readonly SqlSugarScope Db = DataContext.Db;
        private readonly object IssueOutLock = new object();
        public ExportNoticeServer() : base(Db)
        {
        }
@@ -1009,10 +1014,11 @@
                    skuList = skuList.Where(m => m.SkuNo == "100088").ToList();
                }
                skuStrList = skuList.Select(m => m.SkuNo).ToList();
                var areaStr = new List<string>() { "B06", "B07", "B09" };
                var stockRst = new StockServer();
                var stockDetailRst = new StockDetailServer();
                Expression<Func<DataStockDetail, bool>> item = Expressionable.Create<DataStockDetail>()
                    .And(it => it.WareHouseNo == house)
                    .And(it => it.WareHouseNo == house || string.IsNullOrWhiteSpace(it.LocatNo) || (it.WareHouseNo == "W04" && !areaStr.Contains(it.AreaNo)))
                    .AndIF(!string.IsNullOrWhiteSpace(inspectStatus), it => inspectStatus.Contains(it.InspectStatus))
                    .And(m => skuStrList.Contains(m.SkuNo))
                    .AndIF(type == "6", m => m.OwnerNo == ownerNo)//代储出库需要关联货主
@@ -1245,7 +1251,7 @@
                        IsWave = "0",
                        WaveNo = "",
                        IsDespatch = "0",
                        WareHouseNo = model.WareHouseNo,
                        CreateUser = userId,
                    };
@@ -2195,17 +2201,17 @@
                            var time2 = DateTime.Now;//返回时间 .ToString("yyyy-MM-dd HH:mm:ss")
                            ////解析返回数据 
                            var wcsModel = JsonConvert.DeserializeObject<WcsModel>(response);
                            if (wcsModel.StatusCode == 0)
                            var wcsModel = JsonConvert.DeserializeObject<WcsModel2>(response);
                            if (wcsModel.code == 200)
                            {
                                //更改任务的发送返回时间//
                                new TaskServer().EditTaskIssueOk(list2, time1, time2);
                                str += "下发成功";
                            }
                            if (wcsModel.StatusCode == -1)
                            else
                            {
                                new TaskServer().EditTaskIssueNo(list2, time1, time2, wcsModel.Msg);
                                throw new Exception(wcsModel.Msg);
                                new TaskServer().EditTaskIssueNo(list2, time1, time2, wcsModel.message);
                                throw new Exception(wcsModel.message);
                            }
                        }
                        catch (Exception ex)
@@ -2419,12 +2425,9 @@
                        Dictionary<int, decimal> stockQtyDic = new Dictionary<int, decimal>();//托出库物品数
                        var qty = 0m;
                        var house = "";
                        if (notice.Type == "0")
                        {
                            house = "W01";
                        }
                        //分配货物
                        qty += assign.AllotPallets(stockDetail, needQty, pNum, bNum, stockQtyDic, house);
                        qty += assign.AllotPallets(stockDetail, needQty, pNum, bNum, stockQtyDic, notice.WareHouseNo);
                        foreach (var sc in stockQtyDic)
                        {
                            var s = stockDetail.FirstOrDefault(m => m.Id == sc.Key);
@@ -2965,6 +2968,1473 @@
            }
        }
        #endregion
        #region 下发出库、出库完成、重新下发任务、取消任务、异常处理
        public string GetHouseBySo(string soNo)
        {
            try
            {
                var notcie = Db.Queryable<BllExportNotice>().First(m=>m.IsDel == "0" && m.SONo == soNo);
                if (notcie == null)
                {
                    throw new Exception("未查询到出库单信息");
                }
                return notcie.WareHouseNo;
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }
        public List<OutCommandDto> IssueOutHouseLk(string soNo, string outMode, int userId, string url, out string str)
        {
            try
            {
                var outDto1 = new List<OutCommandDto>(); //出库数据的集合(深度为1的储位)
                //记录错误信息的集合 //1:当前要出库的储位正在移出、2 出库的托盘储位信息错误(在储位表中未查询到)、3储位损坏不能出库、4 要出库的托盘正在入库
                var flagList = new List<int>();
                var com = new Common();
                var notice = Db.Queryable<BllExportNotice>().First(m => m.SONo == soNo && m.IsDel == "0");
                if (notice == null)
                {
                    throw new Exception($"未找到{soNo}出库单信息");
                }
                if (notice.WareHouseNo != "W02")
                {
                    throw new Exception("仓库号错误");
                }
                //所有要出库的出库分配信息(未下发的信息和待拣货的信息)
                var list = Db.Queryable<BllExportAllot>().Where(a => a.IsDel == "0" && a.SONo == soNo && (a.Status == "0" || a.Status == "2")).ToList();
                if (list.Count == 0) //判断是否有需要下发的出库流水
                {
                    throw new Exception("当前出库单据无需要下发的托盘");
                }
                #region 集合
                //要出库的托盘集合
                var outLpnList = list.Select(m => m.PalletNo).ToList();
                //要出库的明细集合
                var outStockDetail = Db.Queryable<DataStockDetail>().Where(m => m.IsDel == "0" && outLpnList.Contains(m.PalletNo)).ToList();
                //物料编码表
                var skuList = Db.Queryable<SysMaterials>().Where(w => w.IsDel == "0");
                //包装表
                var packagList = Db.Queryable<SysPackag>().Where(w => w.IsDel == "0");
                Db.BeginTran();
                try
                {
                    List<LogTask> logTaskList = new List<LogTask>();//此次出库任务集合,为应对同托盘不同物料出库
                    var i = 0;
                    var outLocatelist1 = Db.Queryable<SysStorageLocat>().Where(m => m.IsDel == "0" && m.AreaNo == "B02" && m.Flag == "0").ToList();
                    var outLocatelist2 = Db.Queryable<SysStorageLocat>().Where(m => m.IsDel == "0" && m.AreaNo == "B05" && m.Flag == "0").ToList();
                    //循环分配的信息生成出库任务
                    foreach (var item in list)
                    {
                        var outModeLocate = "";
                        if (outMode == "1")
                        {
                            if (i < outLocatelist1.Count)
                            {
                                outModeLocate = outLocatelist1[i].LocatNo;
                            }
                            else
                            {
                                var j = i % outLocatelist1.Count;
                                outModeLocate = outLocatelist1[j].LocatNo;
                            }
                        }
                        else if(outMode == "2")
                        {
                            if (i < outLocatelist1.Count)
                            {
                                outModeLocate = outLocatelist2[i].LocatNo;
                            }
                            else
                            {
                                var j = i % outLocatelist1.Count;
                                outModeLocate = outLocatelist2[j].LocatNo;
                            }
                        }
                        var taskNoStr = "";
                        // 储位号
                        var locateNo = outStockDetail.First(m => m.PalletNo == item.PalletNo).LocatNo;
                        #region 判断
                        //判断托盘是否在库内
                        if (string.IsNullOrWhiteSpace(locateNo)) //库外
                        {
                            //判断托盘是否在入库中
                            var imBl = com.GetImTask(item.PalletNo);
                            if (imBl != null)
                            {
                                flagList.Add(4);
                                continue;
                            }
                            //判断是否是已经出过库又回库(状态为待拣货的)
                            if (item.Status == "0")
                            {
                                //如果不在仓库内,当前分配信息直接更新出库完成
                                item.Status = "2";//状态
                                item.OutMode = outModeLocate;//出库口
                                Db.Updateable(item).ExecuteCommand();
                                var noticeDetail = Db.Queryable<BllExportNoticeDetail>().First(m => m.IsDel == "0" && m.Id == item.SODetailNo);
                                if (noticeDetail != null) //更新出库单据的下发数量
                                {
                                    noticeDetail.FactQty += item.Qty;
                                    Db.Updateable(noticeDetail).ExecuteCommand();
                                }
                                //var notice2 = Db.Queryable<BllExportNotice>().First(m => m.IsDel == "0" && m.SONo == item.SONo);
                                if (notice.Status == "0" || notice.Status == "1" || notice.Status == "2")
                                {
                                    var detailList = Db.Queryable<BllExportNoticeDetail>().Where(m => m.IsDel == "0" && m.SONo == item.SONo).ToList();
                                    if (detailList.Count(m => m.Qty >= m.AllotQty) > 0)
                                    {
                                        notice.Status = "3"; //变更状态为正在执行
                                        Db.Updateable(notice).ExecuteCommand();
                                    }
                                }
                            }
                            flagList.Add(0);
                            continue;
                        }
                        var locate = Db.Queryable<SysStorageLocat>().First(m => m.LocatNo == locateNo && m.IsDel == "0");//当前出库的储位信息
                        if (locate == null)
                        {
                            flagList.Add(2);
                            continue;
                        }
                        //判断储位标志是否为损坏
                        if (locate.Flag == "2")
                        {
                            flagList.Add(3);
                            continue;
                        }
                        #endregion
                        if (locate.Status == "1") //有物品
                        {
                            #region 添加出库任务
                            var taskNo = new Common().GetMaxNo("TK");
                            var exTask = new LogTask    //出库任务
                            {
                                TaskNo = taskNo,
                                Sender = "WMS",
                                Receiver = "WCS",
                                IsSuccess = 0, //是否下发成功 0失败 1成功
                                StartLocat = locate.LocatNo,//起始位置
                                EndLocat = outModeLocate,//目标位置
                                PalletNo = item.PalletNo,//托盘码
                                IsSend = 1,//是否可再次下发
                                IsCancel = 1,//是否可取消
                                IsFinish = 1,//是否可完成
                                Type = "1",//任务类型 0 入库任务 1 出库任务  2 移库任务
                                Status = "0",//任务状态0:等待执行1正在执行2执行完成
                                OrderType = "1",//0 入库单 1 出库单  2 盘点单  3 移库单
                                Msg = "从" + locate.LocatNo + "到" + outModeLocate + "的出库任务", //关键信息
                            };
                            Db.Insertable(exTask).ExecuteCommand();
                            logTaskList.Add(exTask);
                            outDto1.Add(new OutCommandDto()
                            {
                                TaskNo = exTask.TaskNo, // 任务号
                                TaskType = "1",// 任务类型 (出库)0入 1出 2移
                                PalletNo = item.PalletNo,//托盘号
                                StartLocate = locate.LocatNo, // 起始位置
                                StartRoadway = locate.RoadwayNo,//其实巷道
                                EndLocate = outModeLocate, // 目标位置
                                Order = 999,
                                Type  = PLCTypeEnum.AGV
                            });
                            taskNoStr = exTask.TaskNo;
                            #endregion
                            #region 改变数据
                            if (item.Status == "0")//判断托盘是否下发过
                            {
                                var noticeDetail = Db.Queryable<BllExportNoticeDetail>().First(m => m.IsDel == "0" && m.Id == item.SODetailNo);
                                if (noticeDetail != null) //更新出库单据的下发数量
                                {
                                    noticeDetail.FactQty += item.Qty;
                                    Db.Updateable(noticeDetail).ExecuteCommand();
                                }
                                //var notice2 = Db.Queryable<BllExportNotice>().First(m => m.IsDel == "0" && m.SONo == item.SONo);
                                if (notice.Status == "0" || notice.Status == "1" || notice.Status == "2")
                                {
                                    var detailList = Db.Queryable<BllExportNoticeDetail>().Where(m => m.IsDel == "0" && m.SONo == item.SONo).ToList();
                                    if (detailList.Count(m => m.Qty >= m.AllotQty) > 0)
                                    {
                                        notice.Status = "3"; //变更状态为正在执行
                                        Db.Updateable(notice).ExecuteCommand();
                                    }
                                }
                            }
                            locate.Status = "3"; //要出库的储位改变状态 正在出库
                            Db.Updateable(locate).ExecuteCommand();
                            var locate2 = Db.Queryable<SysStorageLocat>().First(m => m.LocatNo == outModeLocate && m.IsDel == "0");//当前出库的目标储位信息
                            locate2.Status = "4";
                            Db.Updateable(locate2).ExecuteCommand();
                            item.TaskNo = taskNoStr; // 出库分配信息中更新任务号
                            item.Status = "1"; // 出库分配信息状态改为正在执行
                            //item.UnstackingMode = unstackingMode2;//拆垛方式
                            item.OutMode = outModeLocate;//出库口
                            //item.LoadingAddre = unstackingMode2 == "0" ? loadingAddre : "";//装车口
                            Db.Updateable(item).ExecuteCommand();
                            #endregion
                            flagList.Add(0);
                            i++;
                        }
                        else if (locate.Status == "3") //出库中
                        {
                            #region 改变数据
                            //判断是否是已经出过库又回库(状态为待拣货的 1)
                            if (item.Status == "0")
                            {
                                var noticeDetail = Db.Queryable<BllExportNoticeDetail>().First(m => m.IsDel == "0" && m.Id == item.SODetailNo);
                                if (noticeDetail != null) //更新出库单据的下发数量
                                {
                                    noticeDetail.FactQty += item.Qty;
                                    Db.Updateable(noticeDetail).ExecuteCommand();
                                }
                                //var notice2 = Db.Queryable<BllExportNotice>().First(m => m.IsDel == "0" && m.SONo == item.SONo);
                                if (notice.Status == "0" || notice.Status == "1" || notice.Status == "2")
                                {
                                    var detailList = Db.Queryable<BllExportNoticeDetail>().Where(m => m.IsDel == "0" && m.SONo == item.SONo).ToList();
                                    if (detailList.Count(m => m.Qty >= m.AllotQty) > 0)
                                    {
                                        notice.Status = "3"; //变更状态为正在执行
                                        Db.Updateable(notice).ExecuteCommand();
                                    }
                                }
                            }
                            var taskNo = Db.Queryable<LogTask>().First(m => m.OrderType == "1" && m.TaskNo != item.TaskNo && m.Status == "1" && m.PalletNo == item.PalletNo);
                            if (taskNo == null)
                            {
                                taskNo = logTaskList.FirstOrDefault(m => m.PalletNo == item.PalletNo);//当前有同托盘不同物料出库
                            }
                            if (taskNo == null)
                            {
                                throw new Exception($"托盘号:{item.PalletNo},出库异常");
                            }
                            item.TaskNo = taskNo.TaskNo;
                            item.Status = "1"; // 出库分配信息状态改为正在执行
                            item.OutMode = item.OutMode;//出库口
                            //item.UnstackingMode = unstackingMode2;//拆垛模式
                            Db.Updateable(item).ExecuteCommand();
                            flagList.Add(0);
                            #endregion
                        }
                        else if (locate.Status == "5") //移出中
                        {
                            flagList.Add(1);
                        }
                    }
                    //添加操作日志记录
                    var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库单据", soNo, "出库", $"点击出库按钮出库单号为:{soNo}的出库单", userId);
                    Db.CommitTran();
                    str = string.Empty;
                    if (flagList.Count(m => m == 0) > 0)
                    {
                        str += "0.下发成功、";
                    }
                    if (flagList.Count(m => m == 1) > 0)
                    {
                        str += "1.当前要出库的储位正在移出、";
                    }
                    if (flagList.Count(m => m == 2) > 0)
                    {
                        str += "2.出库的托盘储位信息错误(在储位表中未查询到)、";
                    }
                    if (flagList.Count(m => m == 3) > 0)
                    {
                        str += "4.储位损坏不能出库、";
                    }
                    if (flagList.Count(m => m == 4) > 0)
                    {
                        str += "3.要出库的托盘正在入库、";
                    }
                    if (flagList.Count(m => m == 5) > 0)
                    {
                        str += "3.要出库的托盘正在拆托请稍后下发、";
                    }
                    if (outDto1.Count > 0)
                    {
                        // 正式运行程序放开
                        var list2 = outDto1.Select(m => m.TaskNo).ToList();
                        var jsonData = JsonConvert.SerializeObject(outDto1);
                        string response = "";
                        try
                        {
                            var time1 = DateTime.Now;//发送时间 .ToString("yyyy-MM-dd HH:mm:ss")
                            //response = HttpHelper.DoPost(url, jsonData, "下发给WCS出库命令", "WCS");
                            var time2 = DateTime.Now;//返回时间 .ToString("yyyy-MM-dd HH:mm:ss")
                            //////解析返回数据
                            //var wcsModel = JsonConvert.DeserializeObject<WcsModel>(response);
                            //if (wcsModel.StatusCode == 0)
                            //{
                            //    //更改任务的发送返回时间//
                                new TaskServer().EditTaskIssueOk(list2, time1, time2);
                                str += "下发成功";
                            //}
                            //if (wcsModel.StatusCode == -1)
                            //{
                            //    new TaskServer().EditTaskIssueNo(list2, time1, time2, wcsModel.Msg);
                            //    throw new Exception(wcsModel.Msg);
                            //}
                        }
                        catch (Exception ex)
                        {
                            throw new Exception(ex.Message);
                        }
                    }
                    return outDto1;
                }
                catch (Exception e)
                {
                    Db.RollbackTran();
                    throw new Exception(e.Message);
                }
                #endregion
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }
        public List<OutCommandDto> IssueOutHouseMk(string soNo, string outMode, int userId, string url, out string str)
        {
            try
            {
                #region 集合
                var outDto1 = new List<OutCommandDto>(); //先出库数据的集合(深度为1的储位)
                var outDto2 = new List<OutCommandDto>(); //后出库数据的集合(深度为2的储位)
                var moveDto = new List<OutCommandDto>(); //要移库数据的集合
                //记录错误信息的集合
                var flagList = new List<int>();//1:当前要出库的储位正在移出、2 出库的托盘储位信息错误(在储位表中未查询到)、3储位损坏不能出库、4 要出库的托盘正在入库
                #endregion
                var com = new Common();
                var allot = new AllotLocation();
                var notice = Db.Queryable<BllExportNotice>().First(m => m.SONo == soNo && m.IsDel == "0");
                if (notice == null)
                {
                    throw new Exception($"未找到{soNo}出库单信息");
                }
                //所有要出库的出库分配信息(未下发的信息和待拣货的信息)
                var list = Db.Queryable<BllExportAllot>().Where(a => a.IsDel == "0" && a.SONo == soNo && (a.Status == "0" || a.Status == "2")).ToList();
                if (list.Count == 0) //判断是否有需要下发的出库流水
                {
                    throw new Exception("当前出库单据无需要下发的托盘");
                }
                #region 集合
                //要出库的托盘集合
                var outLpnList = list.Select(m => m.PalletNo).ToList();
                //要出库的明细集合
                var outStockDetail = Db.Queryable<DataStockDetail>().Where(m => m.IsDel == "0" && outLpnList.Contains(m.PalletNo)).ToList();
                //所有要出库的储位集合
                var locateListStrs = outStockDetail.Where(m=> !string.IsNullOrWhiteSpace(m.LocatNo)).Select(m => m.LocatNo).Distinct().ToList();
                //物料编码表
                var skuList = Db.Queryable<SysMaterials>().Where(w => w.IsDel == "0");
                //包装表
                var packagList = Db.Queryable<SysPackag>().Where(w => w.IsDel == "0");
                Db.BeginTran();
                try
                {
                    List<LogTask> logTaskList = new List<LogTask>();//此次出库任务集合,为应对同托盘不同物料出库
                    //循环分配的信息生成出库任务
                    foreach (var item in list)
                    {
                        var taskNoStr = "";
                        // 储位号
                        var locateNo = outStockDetail.First(m => m.PalletNo == item.PalletNo).LocatNo;
                        #region 判断托盘是否在库内
                        //判断托盘是否在库内
                        if (string.IsNullOrWhiteSpace(locateNo)) //库外
                        {
                            //if (notice.Type == "0")
                            //{
                            //    flagList.Add(5);
                            //    continue;
                            //}
                            //判断托盘是否在入库中
                            var imBl = com.GetImTask(item.PalletNo);
                            if (imBl != null)
                            {
                                flagList.Add(4);
                                continue;
                            }
                            //判断是否是已经出过库又回库(状态为待拣货的 1)
                            if (item.Status == "0")
                            {
                                //如果不在仓库内,当前分配信息直接更新出库完成
                                item.Status = "2";//状态
                                item.OutMode = outMode;//出库口
                                Db.Updateable(item).ExecuteCommand();
                                var noticeDetail = Db.Queryable<BllExportNoticeDetail>().First(m => m.IsDel == "0" && m.Id == item.SODetailNo);
                                if (noticeDetail != null) //更新出库单据的下发数量
                                {
                                    noticeDetail.FactQty += item.Qty;
                                    Db.Updateable(noticeDetail).ExecuteCommand();
                                }
                                //var notice2 = Db.Queryable<BllExportNotice>().First(m => m.IsDel == "0" && m.SONo == item.SONo);
                                if (notice.Status == "0" || notice.Status == "1" || notice.Status == "2")
                                {
                                    var detailList = Db.Queryable<BllExportNoticeDetail>().Where(m => m.IsDel == "0" && m.SONo == item.SONo).ToList();
                                    if (detailList.Count(m => m.Qty >= m.AllotQty) > 0)
                                    {
                                        notice.Status = "3"; //变更状态为正在执行
                                        Db.Updateable(notice).ExecuteCommand();
                                    }
                                }
                            }
                            flagList.Add(0);
                            continue;
                        }
                        //判断储位
                        var locate = Db.Queryable<SysStorageLocat>().First(m => m.LocatNo == locateNo && m.IsDel == "0");//当前出库的储位信息
                        if (locate == null)
                        {
                            flagList.Add(2);
                            continue;
                        }
                        //判断储位标志是否为损坏
                        if (locate.Flag == "2")
                        {
                            flagList.Add(3);
                            continue;
                        }
                        #endregion
                        if (locate.Status == "1") //有物品
                        {
                            var row1 = int.Parse(locate.LocatNo.Substring(2,2));
                            var row2 = int.Parse(locate.AisleOne.Substring(2, 2));
                            //需要移库的信息
                            var NeedMoveInfo = IsNeedMoveLocate(locate, locateListStrs, out int isOut);
                            if (isOut == 1)
                            {
                                //巷道组中有入库或移入的储位,或者是当前储位前有储位未下发成功的任务
                                flagList.Add(2);
                                continue;
                            }
                            if (NeedMoveInfo.Count > 0)//需要移库
                            {
                                //判断库内空储位是否够
                                var okRoad = Db.Queryable<SysStorageRoadway>().Where(m => m.Status == "0" && m.IsDel == "0" && m.WareHouseNo == notice.WareHouseNo).Select(m => m.RoadwayNo).ToList();
                                var nullSlotNum = Db.Queryable<SysStorageLocat>().Count(m => m.RoadwayNo != locate.RoadwayNo && okRoad.Contains(m.RoadwayNo) && m.Status == "0");
                                //判断空储位的数量是否大于需要移库的数量
                                if (nullSlotNum >= NeedMoveInfo.Count)
                                {
                                    var isYk = false;
                                    foreach (var s in NeedMoveInfo)
                                    {
                                        //储位列
                                        var rows = int.Parse(s.Substring(2,2));
                                        //获取移库储位
                                        var moveAddress = GetMiJiMoveAddress(s, locate.AisleOne);
                                        var tary = Db.Queryable<DataStockDetail>().First(m => m.LocatNo == s);
                                        if (string.IsNullOrWhiteSpace(moveAddress)) // 判断是否获取到移库的库位
                                        {
                                            isYk = true;
                                            flagList.Add(5);//出库前有货物,需移库但未查询到空储位
                                            break; //没有移库的库位了
                                        }
                                        else
                                        {
                                            //判断托盘有没有回移的任务
                                            //var hy = GetHyTask(item.ExportStockCode);
                                            //if (hy != null)
                                            //{
                                            //    var hyentity = dataContext.WmsExportTask.FirstOrDefault(m => m.TaskId == hy.TaskId);
                                            //    if (hyentity != null)
                                            //    {
                                            //        isYk = true;
                                            //        msgList.Add(6);//出库前有货物,需移库但是回移托盘
                                            //        break; //没有移库的库位了
                                            //    }
                                            //}
                                            var ykTaskNo = new Common().GetMaxNo("TK");
                                            var ykTask = new LogTask    //出库任务
                                            {
                                                TaskNo = ykTaskNo,
                                                Sender = "WMS",
                                                Receiver = "WCS",
                                                IsSuccess = 0, //是否下发成功 0失败 1成功
                                                StartLocat = s,//起始位置
                                                EndLocat = moveAddress,//outMode,//目标位置
                                                PalletNo = tary.PalletNo,//托盘码
                                                IsSend = 1,//是否可再次下发
                                                IsCancel = 1,//是否可取消
                                                IsFinish = 1,//是否可完成
                                                Type = "2",//任务类型 0 入库任务 1 出库任务  2 移库任务
                                                Status = "0",//任务状态0:等待执行1正在执行2执行完成
                                                OrderType = "1",//0 入库单 1 出库单  2 盘点单  3 移库单
                                                Msg = "从" + locate.LocatNo + "到" + moveAddress + "的移库任务", //关键信息
                                            };
                                            Db.Insertable(ykTask).ExecuteCommand();
                                            logTaskList.Add(ykTask);
                                            outDto1.Add(new OutCommandDto()
                                            {
                                                PalletNo = item.PalletNo,//托盘号
                                                StartLocate = locate.LocatNo, // 起始位置
                                                StartRoadway = locate.RoadwayNo,//其实巷道
                                                EndLocate = moveAddress,//outMode, // 目标位置
                                                TaskNo = ykTaskNo, // 任务号
                                                TaskType = "2",// 任务类型 (出库)0入 1出 2移
                                                Order = Math.Abs(row2 - rows),
                                                Type = PLCTypeEnum.ShuttleCar
                                            });
                                            var slotChange = Db.Queryable<SysStorageLocat>().First(m => m.LocatNo == s);
                                            var slotChange2 = Db.Queryable<SysStorageLocat>().First(m => m.LocatNo == moveAddress);
                                            slotChange.Status = "5"; //改变状态(正在出库)
                                            slotChange2.Status = "4"; // 改变状态(正在移入)
                                            Db.Updateable(slotChange).ExecuteCommand();
                                            Db.Updateable(slotChange2).ExecuteCommand();
                                        }
                                    }
                                    if (isYk)
                                    {
                                        break;
                                    }
                                }
                                else
                                {
                                    flagList.Add(5);
                                    break;
                                }
                            }
                            #region 添加出库任务
                            var taskNo = new Common().GetMaxNo("TK");
                            var exTask = new LogTask    //出库任务
                            {
                                TaskNo = taskNo,
                                Sender = "WMS",
                                Receiver = "WCS",
                                IsSuccess = 0, //是否下发成功 0失败 1成功
                                StartLocat = locate.LocatNo,//起始位置
                                EndLocat = outMode,//outMode,//目标位置
                                PalletNo = item.PalletNo,//托盘码
                                IsSend = 1,//是否可再次下发
                                IsCancel = 1,//是否可取消
                                IsFinish = 1,//是否可完成
                                Type = "1",//任务类型 0 入库任务 1 出库任务  2 移库任务
                                Status = "0",//任务状态0:等待执行1正在执行2执行完成
                                OrderType = "1",//0 入库单 1 出库单  2 盘点单  3 移库单
                                Msg = "从" + locate.LocatNo + "到" + outMode + "的出库任务", //关键信息
                            };
                            Db.Insertable(exTask).ExecuteCommand();
                            logTaskList.Add(exTask);
                            var endroad = allot.RoadwayToStationNum(locate.RoadwayNo, outMode);
                            outDto1.Add(new OutCommandDto()
                            {
                                PalletNo = item.PalletNo,//托盘号
                                StartLocate = locate.LocatNo, // 起始位置
                                StartRoadway = locate.RoadwayNo,//起始巷道
                                EndLocate = outMode,//, // 目标位置
                                EndRoadway = endroad,
                                TaskNo = exTask.TaskNo, // 任务号
                                TaskType = "1",// 任务类型 (出库)0入 1出 2移
                                OutMode = outMode,  //出库口
                                Order = Math.Abs(row2 - row1),
                                Type = PLCTypeEnum.ShuttleCar
                            });
                            taskNoStr = exTask.TaskNo;
                            #endregion
                            #region 改变数据
                            if (item.Status == "0")//判断托盘是否下发过
                            {
                                var noticeDetail = Db.Queryable<BllExportNoticeDetail>().First(m => m.IsDel == "0" && m.Id == item.SODetailNo);
                                if (noticeDetail != null) //更新出库单据的下发数量
                                {
                                    noticeDetail.FactQty += item.Qty;
                                    Db.Updateable(noticeDetail).ExecuteCommand();
                                }
                                //var notice2 = Db.Queryable<BllExportNotice>().First(m => m.IsDel == "0" && m.SONo == item.SONo);
                                if (notice.Status == "0" || notice.Status == "1" || notice.Status == "2")
                                {
                                    var detailList = Db.Queryable<BllExportNoticeDetail>().Where(m => m.IsDel == "0" && m.SONo == item.SONo).ToList();
                                    if (detailList.Count(m => m.Qty >= m.AllotQty) > 0)
                                    {
                                        notice.Status = "3"; //变更状态为正在执行
                                        Db.Updateable(notice).ExecuteCommand();
                                    }
                                }
                            }
                            locate.Status = "3"; //要出库的储位改变状态 正在出库
                            Db.Updateable(locate).ExecuteCommand();
                            item.TaskNo = taskNoStr; // 出库分配信息中更新任务号
                            item.Status = "1"; // 出库分配信息状态改为正在执行
                            //item.UnstackingMode = unstackingMode2;//拆垛方式
                            item.OutMode = outMode;//出库口
                            //item.LoadingAddre = unstackingMode2 == "0" ? loadingAddre : "";//装车口
                            Db.Updateable(item).ExecuteCommand();
                            #endregion
                            flagList.Add(0);
                        }
                        else if (locate.Status == "3") //出库中
                        {
                            #region 改变数据
                            //判断是否是已经出过库又回库(状态为待拣货的 1)
                            if (item.Status == "0")
                            {
                                var noticeDetail = Db.Queryable<BllExportNoticeDetail>().First(m => m.IsDel == "0" && m.Id == item.SODetailNo);
                                if (noticeDetail != null) //更新出库单据的下发数量
                                {
                                    noticeDetail.FactQty += item.Qty;
                                    Db.Updateable(noticeDetail).ExecuteCommand();
                                }
                                //var notice2 = Db.Queryable<BllExportNotice>().First(m => m.IsDel == "0" && m.SONo == item.SONo);
                                if (notice.Status == "0" || notice.Status == "1" || notice.Status == "2")
                                {
                                    var detailList = Db.Queryable<BllExportNoticeDetail>().Where(m => m.IsDel == "0" && m.SONo == item.SONo).ToList();
                                    if (detailList.Count(m => m.Qty >= m.AllotQty) > 0)
                                    {
                                        notice.Status = "3"; //变更状态为正在执行
                                        Db.Updateable(notice).ExecuteCommand();
                                    }
                                }
                            }
                            var taskNo = Db.Queryable<LogTask>().First(m => m.OrderType == "1" && m.TaskNo != item.TaskNo && m.Status == "1" && m.PalletNo == item.PalletNo);
                            if (taskNo == null)
                            {
                                taskNo = logTaskList.FirstOrDefault(m => m.PalletNo == item.PalletNo);//当前有同托盘不同物料出库
                            }
                            if (taskNo == null)
                            {
                                throw new Exception($"托盘号:{item.PalletNo},出库异常");
                            }
                            item.TaskNo = taskNo.TaskNo;
                            item.Status = "1"; // 出库分配信息状态改为正在执行
                            item.OutMode = item.OutMode;//出库口
                            //item.UnstackingMode = unstackingMode2;//拆垛模式
                            Db.Updateable(item).ExecuteCommand();
                            flagList.Add(0);
                            #endregion
                        }
                        else if (locate.Status == "5") //移出中
                        {
                            flagList.Add(1);
                        }
                    }
                    outDto1.AddRange(moveDto);
                    outDto1.AddRange(outDto2);
                    //添加操作日志记录
                    var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库单据", soNo, "出库", $"点击出库按钮出库单号为:{soNo}的出库单", userId);
                    Db.CommitTran();
                    str = string.Empty;
                    if (flagList.Count(m => m == 0) > 0)
                    {
                        str += "0.下发成功、";
                    }
                    if (flagList.Count(m => m == 1) > 0)
                    {
                        str += "1.当前要出库的储位正在移出、";
                    }
                    if (flagList.Count(m => m == 2) > 0)
                    {
                        str += "2.出库的托盘储位信息错误(在储位表中未查询到)、";
                    }
                    if (flagList.Count(m => m == 3) > 0)
                    {
                        str += "4.储位损坏不能出库、";
                    }
                    if (flagList.Count(m => m == 4) > 0)
                    {
                        str += "3.要出库的托盘正在入库、";
                    }
                    if (flagList.Count(m => m == 5) > 0)
                    {
                        str += "3.要出库的托盘正在拆托请稍后下发、";
                    }
                    if (outDto1.Count > 0)
                    {
                        // 正式运行程序放开
                        var list2 = outDto1.Select(m => m.TaskNo).ToList();
                        var jsonData = JsonConvert.SerializeObject(outDto1);
                        string response = "";
                        try
                        {
                            var time1 = DateTime.Now;//发送时间 .ToString("yyyy-MM-dd HH:mm:ss")
                            response = HttpHelper.DoPost(url, jsonData, "下发给WCS出库命令", "WCS");
                            var time2 = DateTime.Now;//返回时间 .ToString("yyyy-MM-dd HH:mm:ss")
                            ////解析返回数据
                            var wcsModel = JsonConvert.DeserializeObject<WcsModel2>(response);
                            if (wcsModel.code == 200)
                            {
                                //更改任务的发送返回时间//
                                new TaskServer().EditTaskIssueOk(list2, time1, time2);
                                str += "下发成功";
                            }
                            else
                            {
                                new TaskServer().EditTaskIssueNo(list2, time1, time2, wcsModel.message);
                                throw new Exception(wcsModel.message);
                            }
                        }
                        catch (Exception ex)
                        {
                            throw new Exception(ex.Message);
                        }
                    }
                    return outDto1;
                }
                catch (Exception e)
                {
                    Db.RollbackTran();
                    throw new Exception(e.Message);
                }
                #endregion
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }
        /// <summary>
        /// 判断是否需要进行移库操作
        /// </summary>
        /// <param name="oldAddress">要出库的库位地址</param>
        /// <param name="aisle">通道口</param>
        /// <param name="addressList">要出口的储位集合</param>
        /// <param name="isOut">是否出库 1:有未下发的任务在前面</param>
        /// <returns>需要移库的集合(如果为空则不需移库)</returns>
        private List<string> IsNeedMoveLocate(SysStorageLocat lcoate,List<string> locateStrList, out int isOut)
        {
            var nowAddress = new List<string>(); //需要移库的集合
            // 010101 派列层
            //var bol = String.CompareOrdinal(lcoate.LocatNo, lcoate.AisleOne);
            var sArray = lcoate.LocatNo.Substring(4,2);
            var row = int.Parse(sArray);//储位列
            var sArray2 = lcoate.AisleOne.Substring(4, 2);
            var row2 = int.Parse(sArray2); //通道口列
            isOut = 0;
            var bol = row2 - row > 0;
            //同组的储位集合
            var slotList = Db.Queryable<SysStorageLocat>().Where(m => m.RoadwayNo == lcoate.RoadwayNo).ToList();
            List<string> list;
            if (bol)
            {
                //储位小于通道口   倒序
                list = slotList.Where(m => m.Column < row2 && m.Column > row).Select(m => m.LocatNo).ToList();
            }
            else
            {
                //储位大于通道口   正序
                list = slotList.Where(m => m.Column > row2 && m.Column < row).Select(m => m.LocatNo).ToList();
            }
            if (list.Any())
            {
                //排除掉同巷道组中要出库的储位
                if (locateStrList.Count != 0)
                {
                    list = list.Where(m => !locateStrList.Contains(m)).ToList();
                }
                //判断是否有入库中或正在移入的
                var s = slotList.Where(m => list.Contains(m.LocatNo) && (m.Status == "2" || m.Status == "4")).Select(m => m.LocatNo).ToList();
                if (s.Count > 0)
                {
                    isOut = 1;
                    return nowAddress;
                }
                //判断是否有在当前储位前未下发的任务(防止撞车)
                var w = Db.Queryable<LogTask>().Where(m => list.Contains(m.StartLocat) && m.IsSuccess == 0).Select(m => m.StartLocat).ToList();
                if (w.Count > 0)
                {
                    isOut = 1;
                    return nowAddress;
                }
                if (bol)
                {
                    //储位小于通道口   倒序
                    nowAddress = slotList.Where(m => list.Contains(m.LocatNo) && m.Status == "1").OrderByDescending(m => m.LocatNo).Select(m => m.LocatNo).ToList();
                }
                else
                {
                    //储位大于通道口   正序
                    nowAddress = slotList.Where(m => list.Contains(m.LocatNo) && m.Status == "1").OrderBy(m => m.LocatNo).Select(m => m.LocatNo).ToList();
                }
                if (nowAddress.Count > 0)
                {
                    return nowAddress;
                }
            }
            else
            {
                return nowAddress;
            }
            return nowAddress;
        }
        /// <summary>
        /// 获取移库目标库位 密集库
        /// </summary>
        /// <param name="oldAddress">需要移动的库位地址</param>
        /// <param name="slotOut">需要移动的库位的出口中转位</param>
        /// <param name="billCode">出库单据或是波次单据</param>
        /// <param name="flags">中转口</param>
        /// <param name="refLanWayId">需回移的巷道id</param>
        /// <param name="refLanOutCode">需回移的巷道中转口</param>
        /// <returns>目标库位地址 为"" 直接下发两次出库指令</returns>
        public string GetMiJiMoveAddress(string oldAddress, string slotOut)
        {
            var newAddress = ""; //新库位
            var newLaneWayAddress = ""; //新巷道口库位
            // 获取移库目标储位
            //
            var sArray = oldAddress.Substring(4,2);
            var ceng = int.Parse(sArray);
            //
            var sArray2 = slotOut.Substring(2, 2);
            var row2 = sArray2;
            //十字口
            var shiKou = new List<string>()
            {
                slotOut,
                "070501",
                "071301",
                "070502",
                "071302",
            };
            var shiKou3 = new List<addreClass>();
            foreach (var item in shiKou)
            {
                var a = item.Substring(4, 2);
                var b = item.Substring(2, 2);
                if (int.Parse(a) != ceng) continue;
                var s = Math.Abs(int.Parse(b) - int.Parse(row2));
                if (shiKou3.Any(m => m.distNum == s)) continue;
                shiKou3.Add(new addreClass()
                {
                    slotCode = item,
                    distNum = s
                });
            }
            //根据十字口差值最小的排序
            shiKou3 = shiKou3.OrderBy(m => m.distNum).ToList();
                /**
                //1 移动到最近的空储位,必须回移。
                //根据四向车移动轨迹计算出最近空储位。
                //出库完成后根据批次号 生产日期 出口计算回移储位。
                //2 移动适合存放的组,系统自动计算是否回移。
                //根据批次号 生产日期 出口 物料等计算出移库目标储位
                //出库完成后,判断是否有比当前库位更合适的存储储位,有移动,无不移动。
                */
                var oldSlot = Db.Queryable<SysStorageLocat>().First(m => m.LocatNo == oldAddress);
                if (oldSlot == null)
                {
                    throw new Exception("未能找到储位信息");
                }
                #region 1不需要回移的
                //后期库存托盘表改了后需要加筛选条件托盘的状态(退货/预拣)
                var tray1 = Db.Queryable<DataStockDetail>().Where(m => m.LocatNo == oldAddress).ToList();
                //根据物料、批次、托盘状态(退货/预拣/暂存等)分组判断
                var d = tray1.GroupBy(m => new { m.SkuNo, m.LotNo, m.PalletTags });
                var location = string.Empty;
                if (d.Any())
                {
                    //旧储位同组的储位集合
                    var slotList = Db.Queryable<SysStorageLocat>().Where(m => m.RoadwayNo == oldSlot.RoadwayNo).Select(m => m.LocatNo).ToList();
                    foreach (var item in d)
                    {
                        foreach (var item2 in item)
                        {
                            var okLan = Db.Queryable<SysStorageRoadway>().Where(m => m.Status == "0" && m.IsDel == "0").Select(m => m.RoadwayNo).ToList();
                            var tray2 = Db.Queryable<DataStockDetail>().Where(m => m.SkuNo == item2.SkuNo
                            && m.LotNo == item2.LotNo && !slotList.Contains(m.LocatNo) && m.PalletTags == item2.PalletTags && okLan.Contains(m.RoadwayNo)).ToList();
                            foreach (var s in tray2)
                            {
                                if (string.IsNullOrWhiteSpace(s.RoadwayNo))//判断是否在库外,如是跳过
                                {
                                    continue;
                                }
                                var lan = Db.Queryable<SysStorageLocat>().Where(m => m.RoadwayNo == s.RoadwayNo).OrderBy(m => m.LocatNo).ToList();
                                //判断是否有入库中、出库中、移入中、移出中
                                if (lan.Count(m => m.Status == "2" || m.Status == "3" || m.Status == "4" || m.Status == "5") > 0)
                                {
                                    continue;
                                }
                                if (lan.Count(m => m.Status == "0") > 0)
                                {
                                    var bol = GetBecomingLocation(s.RoadwayNo, ref location);
                                    if (bol && !string.IsNullOrWhiteSpace(location))
                                    {
                                        newAddress = location;
                                        return newAddress;
                                    }
                                }
                            }
                        }
                    }
                }
                #endregion
                #region 2需要回移的
                ////如果没有找到合适的储位
                //if (string.IsNullOrWhiteSpace(newAddress))
                //{
                //    foreach (var s in shiKou3)
                //    {
                //        var r = int.Parse(s.slotCode.Substring(0, 2));
                //        var l = int.Parse(s.slotCode.Substring(2, 2));
                //        var c = int.Parse(s.slotCode.Substring(4, 2));
                //        //查询空储位
                //        var sqlString = $@"select LocatNo,Row,Column,Layer,(ABS(Row-{r}) + ABS(Column-{l}) ) as distNum
                //                from SysStorageLocat where (AisleOneRow  = {r} or AisleTwoRow = {r}) and Status in (0) and
                //                 RoadwayNo !='{oldSlot.RoadwayNo}' and RoadwayNo not in(select RoadwayNo from SysStorageRoadway where Status = 1) order by distNum,SlotCode";
                //        var addressModels = dataContext.ExecuteQuery<addreClass>(sqlString).ToList();
                //        foreach (var item in addressModels)
                //        {                            、
                //            newAddress = item.slotCode;
                //            var dz = newAddress.Split(new char[] { '-' });
                //            var l1 = dz[1];
                //            var c1 = dz[0];
                //            newLaneWayAddress = $"{c1}-{l1}-{a[2]}";
                //            flags = newLaneWayAddress;
                //            var slotModel = dataContext.WmsBaseSlot.FirstOrDefault(m => m.SlotCode == item.slotCode);
                //            var lan = dataContext.WmsBaseSlot.Where(m => m.SlotLanewayId == slotModel.SlotLanewayId).ToList();
                //            if (slotModel.SlotRow > int.Parse(a[2]))
                //            {
                //                // 取最上面一排
                //                lan = lan.OrderBy(m => m.SlotCode).ToList();
                //                for (int i = 0; i < lan.Count; i++)
                //                {
                //                    var slot = dataContext.WmsBaseSlot.FirstOrDefault(m => m.SlotCode == lan[i].SlotCode);
                //                    if (slot.SlotStatus == 0)
                //                    {
                //                        if (i == lan.Count - 1)
                //                        {
                //                            newAddress = lan[lan.Count - 1].SlotCode;
                //                            break;
                //                        }
                //                        else
                //                        {
                //                            continue;
                //                        }
                //                    }
                //                    else
                //                    {
                //                        newAddress = lan[i - 1].SlotCode;
                //                        break;
                //                    }
                //                }
                //            }
                //            else
                //            {
                //                // 取最下面一排
                //                lan = lan.OrderByDescending(m => m.SlotCode).ToList();
                //                for (int i = 0; i < lan.Count; i++)
                //                {
                //                    var slot = dataContext.WmsBaseSlot.FirstOrDefault(m => m.SlotCode == lan[i].SlotCode);
                //                    if (slot.SlotStatus == 0)
                //                    {
                //                        if (i == lan.Count - 1)
                //                        {
                //                            newAddress = lan[lan.Count - 1].SlotCode;
                //                            break;
                //                        }
                //                        else
                //                        {
                //                            continue;
                //                        }
                //                    }
                //                    else
                //                    {
                //                        newAddress = lan[i - 1].SlotCode;
                //                        break;
                //                    }
                //                }
                //            }
                //            //添加回移任务
                //            AddHyTask(oldAddress, newAddress, newLaneWayAddress, oldSlot.SlotLanewayId, slotOut, billCode);
                //            refLanWayId = slotModel.SlotLanewayId;
                //            refLanOutCode = newLaneWayAddress;
                //            //9:锁定储位
                //            var updateSlot = dataContext.WmsBaseSlot.Where(m => m.SlotLanewayId == slotModel.SlotLanewayId).ToList();
                //            var newAddressRow = dataContext.WmsBaseSlot.FirstOrDefault(m => m.SlotCode == newAddress);
                //            if (newAddressRow.SlotRow > int.Parse(a[2]))
                //            {
                //                updateSlot = updateSlot.Where(m => m.SlotRow < newAddressRow.SlotRow && m.SlotRow > int.Parse(a[2])).OrderBy(m => m.SlotCode).ToList();
                //            }
                //            else
                //            {
                //                updateSlot = updateSlot.Where(m => m.SlotRow > newAddressRow.SlotRow && m.SlotRow < int.Parse(a[2])).OrderByDescending(m => m.SlotCode).ToList();
                //            }
                //            foreach (var source in updateSlot)
                //            {
                //                if (source.SlotCode == newAddress)
                //                {
                //                    continue;
                //                }
                //                if (source.SlotStatus == 0)
                //                {
                //                    source.SlotStatus = 8;
                //                }
                //            }
                //            if (updateSlot.Count <= 0)
                //            {
                //                refLanWayId = "";
                //                refLanOutCode = "";
                //            }
                //            dataContext.SubmitChanges();
                //            return newAddress;
                //        }
                //    }
                //}
                return newAddress;
                #endregion
        }
        /// <summary>
        /// 获取移库合适的储位 密集库
        /// </summary>
        /// <param name="laneWayId">合适组的巷道号</param>
        /// <param name="location">分配储位</param>
        /// <returns>true:存在合适储位   False:不存在合适储位</returns>
        private bool GetBecomingLocation(string laneWayId, ref string location)
        {
            bool bl = false;
            // 循环判断当前组是否有剩余储位
            string sqlString = string.Empty;
            location = "";
            // 判断储位组是否有空储位   关联库存明细表可防止储位状态不准确避免造成满入异常//not in ('1','2','4','6','7','8')
            sqlString = $"select LocatNo,Column,AisleOne from SysStorageLocat where RoadwayNo = {laneWayId} and Status in ('0') and LocatNo not in (select LocatNo from DataStockDetail where RoadwayNo = { laneWayId}) order by Row;";
            var slotModel =Db.SqlQueryable<LocateInfo>(sqlString).ToList();
            if (slotModel.Count == 0)
            {
                bl = false;
            }
            else  // 存在空储位
            {
                // 判断当前组合适的储位地址
                var numstr = slotModel[0].AisleOne.Substring(4,2);
                int aisleRow = int.Parse(numstr);
                if (slotModel[0].Column > aisleRow)
                {
                    // 取最上面一排
                    location = slotModel[0].LocatNo;
                }
                else
                {
                    // 取最下面一排
                    location = slotModel[slotModel.Count - 1].LocatNo;
                }
                bl = true;
            }
            return bl;
        }
        private class addreClass
        {
            public string slotCode { get; set; }
            public int distNum { get; set; }
        }
        public class LocateInfo
        {
            public string LocatNo { get; set; }
            public int Column { get; set; }
            public string AisleOne { get; set; }
        }
        /// <summary>
        /// wcs返回的成功信号(出库成功)
        /// </summary>
        /// <param name="taskNo"></param>
        /// <param name="userId"></param>
        /// <exception cref="Exception"></exception>
        public void ExportSuccess(string taskNo, int userId)
        {
            try
            {
                //当前任务信息
                var task = Db.Queryable<LogTask>().First(m => m.TaskNo == taskNo && m.IsDel == "0");
                if (task == null)
                {
                    throw new Exception($"未查询到任务号为:‘{taskNo}’的任务信息");
                }
                if (task.Status == "2")
                {
                    throw new Exception("当前任务已完成");
                }
                Db.BeginTran();
                //库存中当前托盘的信息
                var stockDetail = Db.Queryable<DataStockDetail>().Where(m => m.PalletNo == task.PalletNo).ToList();
                var locateNo = stockDetail.Select(m => m.LocatNo).Distinct().FirstOrDefault();
                //当前任务中的储位信息
                var locate = Db.Queryable<SysStorageLocat>().First(m => m.LocatNo == locateNo);
                try
                {
                    task.Status = "2";//任务状态
                    task.IsSend = 0;
                    task.IsCancel = 0;
                    task.IsFinish = 0;
                    task.FinishDate = DateTime.Now;//完成时间
                    Db.Updateable(task).ExecuteCommand();
                    if (locate != null)
                    {
                        locate.Status = "0"; // 更改当前任务中的储位状态(改为0空储位)
                        Db.Updateable(locate).ExecuteCommand();
                    }
                    foreach (var item in stockDetail)
                    {
                        if (item.SkuNo == "100099")//判断是否是空托出库
                        {
                            //判断总库存是否为0,如果为0删除 否则减去数量
                            var stock = Db.Queryable<DataStock>().First(m => m.SkuNo == "100099");
                            if (stock != null)
                            {
                                if (item.LockQty != null)
                                {
                                    stock.Qty -= item.LockQty.Value;
                                    stock.LockQty -= item.LockQty.Value;
                                    Db.Updateable(stock).ExecuteCommand();
                                }
                                if (stock.Qty == 0)
                                {
                                    Db.Deleteable(stock).ExecuteCommand();
                                }
                            }
                            //托盘状态改为未使用
                            var sCode = Db.Queryable<SysPallets>().First(m => m.PalletNo == item.PalletNo);
                            if (sCode != null)
                            {
                                sCode.Status = "0";
                                Db.Updateable(sCode).ExecuteCommand();
                            }
                            Db.Deleteable(item).ExecuteCommand();
                            continue;
                        }
                        item.LocatNo = "";//储位更改(改为空)
                        item.WareHouseNo = "";//所属仓库更改(改为空)
                        item.RoadwayNo = "";//所属巷道更改(改为空)
                        item.AreaNo = "";//所属区域更改(改为空)
                    }
                    //出库流水(更改状态)
                    var allot = Db.Queryable<BllExportAllot>().Where(m => m.IsDel == "0" && (m.TaskNo == taskNo || (m.Status == "1" && m.PalletNo == task.PalletNo))).ToList();
                    var PalletType = "0"; //0:物料托  1:空托盘托
                    foreach (var item in allot)
                    {
                        if (item.SkuNo == "100099")
                        {
                            item.Status = "5";
                            item.CompleteQty += stockDetail[0].Qty;
                            PalletType = "1";
                        }
                        else
                        {
                            item.Status = "2";
                        }
                    }
                    var endLocateList = Db.Queryable<SysStorageLocat>().Where(m => m.IsDel == "0" && (m.AreaNo == "B02" || m.AreaNo == "B05")).Select(m=>m.LocatNo).ToList();
                    //判断是否是原辅料出库任务  货架储位=》平库储位
                    if ( endLocateList.Contains(task.EndLocat) && PalletType == "0")
                    {
                        //修改目标地址状态
                        var endLocat = Db.Queryable<SysStorageLocat>().First(m => m.IsDel == "0" && m.LocatNo == task.EndLocat);
                        endLocat.Status = "1";
                        Db.Updateable(endLocat).ExecuteCommand();
                        foreach (var item in stockDetail)
                        {
                            item.LocatNo = endLocat.LocatNo;//储位更改(改为空)
                            item.WareHouseNo = endLocat.WareHouseNo;//所属仓库更改(改为空)
                            item.RoadwayNo = endLocat.RoadwayNo;//所属巷道更改(改为空)
                            item.AreaNo = endLocat.AreaNo;//所属区域更改(改为空)
                        }
                    }
                    Db.Updateable(stockDetail).ExecuteCommand();
                    Db.Updateable(allot).ExecuteCommand();
                    if (userId != 0)
                    {
                        //添加操作日志记录
                        var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库日志", taskNo, "完成", $"点击完成按钮、完成任务号为:{taskNo}的任务", userId);
                    }
                    Db.CommitTran();
                }
                catch (Exception ex)
                {
                    Db.RollbackTran();
                    throw new Exception(ex.Message);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("完成反馈失败:" + ex.Message);
            }
        }
        /// <summary>
        /// wcs返回的成功信号(移库成功)
        /// </summary>
        /// <param name="taskNo">任务号</param>
        /// <param name="userId">操作人</param>
        /// <exception cref="Exception"></exception>
        public void RelocationSuccess(string taskNo, int userId)
        {
            try
            {
                //当前任务信息
                var task = Db.Queryable<LogTask>().First(m => m.TaskNo == taskNo && m.IsDel == "0");
                if (task == null)
                {
                    throw new Exception($"未查询到任务号为:‘{taskNo}’的任务信息");
                }
                if (task.Status == "2")
                {
                    throw new Exception("当前任务已完成");
                }
                Db.BeginTran();
                //库存中当前托盘的信息
                var stockDetail = Db.Queryable<DataStockDetail>().Where(m => m.PalletNo == task.PalletNo).ToList();
                //当前任务中的目标储位信息
                //当前任务中的原储位
                var locate = Db.Queryable<SysStorageLocat>().First(m => m.LocatNo == task.StartLocat);
                if (locate == null)
                {
                    throw new Exception($"WMS系统中没有该{task.StartLocat}储位对应的信息");
                }
                var locate2 = Db.Queryable<SysStorageLocat>().First(m => m.LocatNo == task.EndLocat);
                if (locate2 == null)
                {
                    throw new Exception($"WMS系统中没有该{task.EndLocat}储位对应的信息");
                }
                //平库中储位集合
                var pingKuLocate = Db.Queryable<SysStorageLocat>().Where(m => m.WareHouseNo == "W04" && m.IsDel == "0").ToList();
                var pingKuList = pingKuLocate.Select(m => m.LocatNo).ToList();
                try
                {
                    //task.Status = "5";//任务状态
                    ////判断起始目标位置都是平库
                    //if (pingKuList.Contains(task.StartLocat) && pingKuList.Contains(task.EndLocat))
                    //{
                        task.Status = "2";
                    //}
                    task.IsSend = 0;
                    task.IsCancel = 0;
                    task.IsFinish = 0;
                    task.FinishDate = DateTime.Now;//完成时间
                    Db.Updateable(task).ExecuteCommand();
                    #region 修改储位状态
                    if (!pingKuList.Contains(task.StartLocat))
                    {
                        //原储位改为空储位 0
                        locate.Status = "0";
                        Db.Updateable(locate).ExecuteCommand();
                    }
                    //目标储位改为有货物 1
                    locate2.Status = "1";
                    Db.Updateable(locate2).ExecuteCommand();
                    //判断起始目标位置都是平库
                    if ( pingKuList.Contains(task.EndLocat))
                    {
                        foreach (var item in stockDetail)
                        {
                            item.WareHouseNo = locate2.WareHouseNo;
                            item.AreaNo = locate2.AreaNo;
                            item.RoadwayNo = locate2.RoadwayNo;
                            item.LocatNo = locate2.LocatNo;
                        }
                        Db.Updateable(stockDetail).ExecuteCommand();
                    }
                    #endregion
                    Db.CommitTran();
                }
                catch (Exception ex)
                {
                    Db.RollbackTran();
                    throw new Exception(ex.Message);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("完成反馈失败:" + ex.Message);
            }
        }
        /// <summary>
        /// AGV任务取货完成反馈
        /// </summary>
        /// <param name="taskNo"></param>
        public void AGVQuHuoSuccess(string taskNo)
        {
            try
            {
                Db.BeginTran();
                var task = Db.Queryable<LogTask>().First(m=>m.IsDel =="0" && m.TaskNo == taskNo);
                if (task == null)
                {
                    throw new Exception("没有查询到任务信息");
                }
                if (task.Status!="1")
                {
                    throw new Exception("任务状态不是正在执行,请核实");
                }
                var locate = Db.Queryable<SysStorageLocat>().First(m => m.LocatNo == task.StartLocat && m.IsDel == "0");
                if (locate == null)
                {
                    throw new Exception("没有查询到起始储位信息");
                }
                if (locate.WareHouseNo!="W04")
                {
                    throw new Exception("起始储位不是平库储位,请核实");
                }
                locate.Status = "0"; //更改储位状态为空储位
                Db.Updateable(locate).ExecuteCommand();
                //查询出托盘信息  更改库存储位信息
                var stockDetail = Db.Queryable<DataStockDetail>().Where(m => m.IsDel == "0" && m.PalletNo == task.PalletNo).ToList();
                foreach (var item in stockDetail)
                {
                    item.WareHouseNo = "";
                    item.AreaNo = "";
                    item.RoadwayNo = "";
                    item.LocatNo = "";
                }
                Db.Updateable(stockDetail).ExecuteCommand();
                Db.CommitTran();
            }
            catch (Exception e)
            {
                Db.RollbackTran();
                throw new Exception(e.Message);
            }
        }
        #endregion
        #endregion
@@ -4103,9 +5573,6 @@
                                    OutMode = toLocation,  //出库口 
                                    Order = 1,
                                    UnstackingMode=unstackingMode2,//拣货方式 0机器拆托出  1 人工拣货出
                                    CompleteQty= outCount2,  //拆的件数
                                    BoxexQty = outCount,      //总件数
                                });
                                taskNoStr = exTask.TaskNo;
                            }
@@ -4220,9 +5687,7 @@
                                                    OutMode = toLocation,  //目标地址
                                                    Order = 1,
                                                    UnstackingMode = "1",//拣货方式 0机器拆托出  1 人工拣货出
                                                    CompleteQty = 0,  //拆的件数
                                                    BoxexQty = 0,      //总件数
                                                });
                                                #endregion
@@ -4278,9 +5743,6 @@
                                    OutMode = toLocation,  //目标地址
                                    Order = 1,
                                    UnstackingMode = unstackingMode2,//拣货方式 0机器拆托出  1 人工拣货出
                                    CompleteQty = outCount2,  //拆的件数
                                    BoxexQty = outCount,      //总件数
                                });
                                taskNoStr = exTask1.TaskNo;
                                #endregion
@@ -4451,338 +5913,6 @@
            }
        }
        
        //wcs返回的成功信号(出库成功)
        public void ExportSuccess(string taskNo, int userId)
        {
            try
            {
                //当前任务信息
                var task = Db.Queryable<LogTask>().First(m => m.TaskNo == taskNo && m.IsDel == "0");
                if (task == null)
                {
                    throw new Exception($"未查询到任务号为:‘{taskNo}’的任务信息");
                }
                if (task.Status == "2")
                {
                    throw new Exception("当前任务已完成");
                }
                Db.BeginTran();
                //库存中当前托盘的信息
                var stockDetail = Db.Queryable<DataStockDetail>().Where(m => m.PalletNo == task.PalletNo).ToList();
                var locateNo = stockDetail.Select(m => m.LocatNo).Distinct().FirstOrDefault();
                //当前任务中的储位信息
                var locate = Db.Queryable<SysStorageLocat>().First(m => m.LocatNo == locateNo);
                try
                {
                    task.Status = "2";//任务状态
                    task.IsSend = 0;
                    task.IsCancel = 0;
                    task.IsFinish = 0;
                    task.FinishDate = DateTime.Now;//完成时间
                    Db.Updateable(task).ExecuteCommand();
                    if (locate != null)
                    {
                        locate.Status = "0"; // 更改当前任务中的储位状态(改为0空储位)
                        Db.Updateable(locate).ExecuteCommand();
                    }
                    foreach (var item in stockDetail)
                    {
                        if (item.SkuNo == "100099")//判断是否是空托出库
                        {
                            //判断总库存是否为0,如果为0删除 否则减去数量
                            var stock = Db.Queryable<DataStock>().First(m => m.SkuNo == "100099");
                            if (stock != null)
                            {
                                if (item.LockQty != null)
                                {
                                    stock.Qty -= item.LockQty.Value;
                                    stock.LockQty -= item.LockQty.Value;
                                    Db.Updateable(stock).ExecuteCommand();
                                }
                                if (stock.Qty == 0)
                                {
                                    Db.Deleteable(stock).ExecuteCommand();
                                }
                            }
                            //托盘状态改为未使用
                            var sCode = Db.Queryable<SysPallets>().First(m => m.PalletNo == item.PalletNo);
                            if (sCode != null)
                            {
                                sCode.Status = "0";
                                Db.Updateable(sCode).ExecuteCommand();
                            }
                            Db.Deleteable(item).ExecuteCommand();
                            #region 拣货信息
                            //var pickQty = 0;//拣货的数量
                            //var comList = new List<BllCompleteDetail>();
                            //    //添加拣货明细
                            //    var completeDetail = new BllCompleteDetail()
                            //    {
                            //        SONo = "",
                            //        SODetailNo = 0,
                            //        ExportAllotId = 0,
                            //        StockId = exportAllot.StockId,
                            //        BoxNo = item.BoxNo,
                            //        BoxNo2 = item.BoxNo2,
                            //        BoxNo3 = item.BoxNo3,
                            //        LotNo = exportAllot.LotNo,
                            //        LotText = exportAllot.LotText,
                            //        SupplierLot = exportAllot.SupplierLot,
                            //        SkuNo = exportAllot.SkuNo,
                            //        SkuName = exportAllot.SkuName,
                            //        Standard = exportAllot.Standard,
                            //        PalletNo = palletNo,
                            //        CompleteQty = item.Qty,
                            //        CreateUser = userId
                            //    };
                            //    comList.Add(completeDetail);
                            //    //删除库存箱码明细
                            //    Db.Deleteable(item).ExecuteCommand();
                            //    pickQty += item.Qty;
                            //    exportAllot.Status = "5"; //待回库 : 已完成
                            //    exportAllot.CompleteQty += item.Qty; //拣货数量
                            //    exportAllot.UpdateUser = userId; //修改人
                            //    exportAllot.UpdateTime = serverTime; //修改时间
                            //    Db.Updateable(exportAllot).ExecuteCommand();
                            //    //验证拣货信息是否为已完成
                            //    if (exportAllot.Status == "5")
                            //    {
                            //        break;
                            //    }
                            //Db.Insertable(comList).ExecuteCommand();
                            #endregion
                            continue;
                        }
                        item.LocatNo = "";//储位更改(改为空)
                        item.WareHouseNo = "";//所属仓库更改(改为空)
                        item.RoadwayNo = "";//所属巷道更改(改为空)
                        item.AreaNo = "";//所属区域更改(改为空)
                        Db.Updateable(item).ExecuteCommand();
                    }
                    //出库流水(更改状态)
                    var allot = Db.Queryable<BllExportAllot>().Where(m => m.IsDel == "0" && (m.TaskNo == taskNo || (m.Status == "1" && m.PalletNo == task.PalletNo))).ToList();
                    var PalletType = "0"; //0:物料托  1:空托盘托
                    var soNo = "";
                    var sku = "";
                    foreach (var item in allot)
                    {
                        if (item.SkuNo == "100099")
                        {
                            item.Status = "5";
                            item.CompleteQty += stockDetail[0].Qty;
                            PalletType = "1";
                        }
                        else
                        {
                            item.Status = "2";
                            soNo = item.SONo;
                            sku = item.SkuNo;
                        }
                    }
                    //下发四楼调度AGV的任务
                    if ((task.EndLocat == "outMode" || task.EndLocat == "outMode") && PalletType == "0")
                    {
                        foreach (var item in allot)
                        {
                            var detail = Db.Queryable<DataStockDetail>().First(m => m.Id == item.StockId);
                            detail.SONo = item.SONo;
                            Db.Updateable(detail).ExecuteCommand();
                        }
                        var locatePing = new AllotLocation().GetPingLocate(soNo, sku);
                        if (locatePing == null)
                        {
                            throw new Exception("平库未查询到空位置");
                        }
                        var exTask = new LogTask    //出库任务
                        {
                            TaskNo = new Common().GetMaxNo("TK"),
                            Sender = "WMS",
                            Receiver = "AGV",
                            IsSuccess = 0, //是否下发成功 0失败 1成功
                            StartLocat = task.EndLocat,//起始位置
                            EndLocat = locatePing.LocatNo,//outMode,//目标位置
                            PalletNo = task.PalletNo,//托盘码
                            IsSend = 1,//是否可再次下发
                            IsCancel = 1,//是否可取消
                            IsFinish = 1,//是否可完成
                            Type = "1",//任务类型 0 入库任务 1 出库任务  2 移库任务
                            Status = "0",//任务状态0:等待执行1正在执行2执行完成
                            OrderType = "1",//0 入库单 1 出库单  2 盘点单  3 移库单
                            Msg = "从" + task.EndLocat + "到" + locatePing.LocatNo + "的出库任务", //关键信息
                        };
                        Db.Insertable(exTask).ExecuteCommand();
                        var outDto = new List<OutCommandDto>
                        {
                            new OutCommandDto()
                            {
                                PalletNo = task.PalletNo,//托盘号
                                StartLocate = task.EndLocat, // 起始位置
                                StartRoadway = "",//其实巷道
                                EndLocate = locatePing.LocatNo,//outMode, // 目标位置
                                TaskNo = exTask.TaskNo, // 任务号
                                TaskType = "1",// 任务类型 (出库)0入 1出 2移
                                OutMode = "",  //出库口
                                Order = 1,
                                //UnstackingMode = unstackingMode2,//拣货方式 0机器拆托出  1 人工拣货出
                                //CompleteQty = outCount2,  //拆的件数
                                //BoxexQty = outCount,      //总件数
                            }
                        };
                        // 正式运行程序放开
                        var list2 = outDto.Select(m => m.TaskNo).ToList();
                        var jsonData = JsonConvert.SerializeObject(outDto);
                        string response = "";
                        try
                        {
                            var time1 = DateTime.Now;//发送时间 .ToString("yyyy-MM-dd HH:mm:ss")
                            //response = HttpHelper.DoPost(url, jsonData, "下发给WCS出库命令", "WCS");
                            var time2 = DateTime.Now;//返回时间 .ToString("yyyy-MM-dd HH:mm:ss")
                            //////解析返回数据
                            //var wcsModel = JsonConvert.DeserializeObject<WcsModel>(response);
                            //if (wcsModel.StatusCode == 0)
                            //{
                            //更改任务的发送返回时间//
                            new TaskServer().EditTaskIssueOk(list2, time1, time2);
                            //}
                            //if (wcsModel.StatusCode == -1)
                            //{
                            //    new TaskServer().EditTaskIssueNo(list2, time1, time2, wcsModel.Msg);
                            //    throw new Exception(wcsModel.Msg);
                            //}
                        }
                        catch (Exception ex)
                        {
                            throw new Exception(ex.Message);
                        }
                    }
                    Db.Updateable(allot).ExecuteCommand();
                    if (userId != 0)
                    {
                        //添加操作日志记录
                        var k = new OperationSOServer().AddLogOperationSo("出库作业", "出库日志", taskNo, "完成", $"点击完成按钮、完成任务号为:{taskNo}的任务", userId);
                    }
                    Db.CommitTran();
                }
                catch (Exception ex)
                {
                    Db.RollbackTran();
                    throw new Exception(ex.Message);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("完成反馈失败:" + ex.Message);
            }
        }
        /// <summary>
        /// wcs返回的成功信号(移库成功)
        /// </summary>
        /// <param name="taskNo">任务号</param>
        /// <param name="userId">操作人</param>
        /// <exception cref="Exception"></exception>
        public void RelocationSuccess(string taskNo, int userId)
        {
            try
            {
                //当前任务信息
                var task = Db.Queryable<LogTask>().First(m => m.TaskNo == taskNo && m.IsDel == "0");
                if (task == null)
                {
                    throw new Exception($"未查询到任务号为:‘{taskNo}’的任务信息");
                }
                if (task.Status == "2")
                {
                    throw new Exception("当前任务已完成");
                }
                Db.BeginTran();
                //库存中当前托盘的信息
                var stockDetail = Db.Queryable<DataStockDetail>().Where(m => m.PalletNo == task.PalletNo).ToList();
                //当前任务中的目标储位信息
                //当前任务中的原储位
                var locate = Db.Queryable<SysStorageLocat>().First(m => m.LocatNo == task.StartLocat);
                if (locate == null)
                {
                    throw new Exception($"WMS系统中没有该{task.StartLocat}储位对应的信息");
                }
                var locate2 = Db.Queryable<SysStorageLocat>().First(m => m.LocatNo == task.EndLocat);
                if (locate2 == null)
                {
                    throw new Exception($"WMS系统中没有该{task.EndLocat}储位对应的信息");
                }
                try
                {
                    task.Status = "2";//任务状态
                    task.IsSend = 0;
                    task.IsCancel = 0;
                    task.IsFinish = 0;
                    task.FinishDate = DateTime.Now;//完成时间
                    Db.Updateable(task).ExecuteCommand();
                    #region 修改储位状态
                    //原储位改为空储位 0
                    locate.Status = "0";
                    Db.Updateable(locate).ExecuteCommand();
                    //目标储位改为有货物 1
                    locate2.Status = "1";
                    Db.Updateable(locate2).ExecuteCommand();
                    foreach (var item in stockDetail)
                    {
                        item.WareHouseNo = locate2.WareHouseNo;
                        item.AreaNo = locate2.AreaNo;
                        item.RoadwayNo = locate2.RoadwayNo;
                        item.LocatNo = locate2.LocatNo;
                    }
                    Db.Updateable(stockDetail).ExecuteCommand();
                    #endregion
                    Db.CommitTran();
                }
                catch (Exception ex)
                {
                    Db.RollbackTran();
                    throw new Exception(ex.Message);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("完成反馈失败:" + ex.Message);
            }
        }
        //重新下发出库任务
        public OutCommandDto AgainSendSoTask(string taskNo, int userId, string url)
        {
@@ -4839,17 +5969,17 @@
                    var time2 = DateTime.Now;//返回时间 .ToString("yyyy-MM-dd HH:mm:ss")
                    ////解析返回数据 
                    var wcsModel = JsonConvert.DeserializeObject<WcsModel>(response);
                    if (wcsModel.StatusCode == 0)
                    var wcsModel = JsonConvert.DeserializeObject<WcsModel2>(response);
                    if (wcsModel.code == 200)
                    {
                        //更改任务的发送返回时间//
                        new TaskServer().EditTaskIssueOk(list, time1, time2);
                    }
                    if (wcsModel.StatusCode == -1)
                    else
                    {
                        new TaskServer().EditTaskIssueNo(list, time1, time2, wcsModel.Msg);
                        throw new Exception($"wcs返回状态异常:{wcsModel.Msg}");
                        new TaskServer().EditTaskIssueNo(list, time1, time2, wcsModel.message);
                        throw new Exception($"wcs返回状态异常:{wcsModel.message}");
                    }
                }
                catch (Exception ex)