kazelee
2025-05-19 b079910e5de15863c26e479ffab15cc45d706f1a
测试修复轮询出库、抽检流程的问题
1 文件已重命名
17个文件已修改
3个文件已删除
380 ■■■■■ 已修改文件
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/5c57b4d0-dbd7-49e3-9f10-3d5a4d6dc3f3.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/7b1f7e4e-45eb-4263-a455-827cb67bccfe.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/ab784fdf-fa93-4eaa-9449-8122428bc0ae.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
Controllers/DebugController.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dtos/Request/DebugRequest.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3.DSZSH.csproj 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Helpers/AgvHelper.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Helpers/DbHelper.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_CG_Detail.cs 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_Check_Detail.cs 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_Container_Item.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_Outbound_Detail.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_Outbound_Order.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_Task.cs 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Program.cs 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServiceCore/CheckCore.cs 43 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServiceCore/OutboundCore.cs 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServiceCore/ShiftCore.cs 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Services/DebugService.cs 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Services/MoboxService.cs 133 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Services/WmsService.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/5c57b4d0-dbd7-49e3-9f10-3d5a4d6dc3f3.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/7b1f7e4e-45eb-4263-a455-827cb67bccfe.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.DSZSH/FileContentIndex/ab784fdf-fa93-4eaa-9449-8122428bc0ae.vsidx
Binary files differ
Controllers/DebugController.cs
@@ -29,7 +29,7 @@
        {
            return DebugService.AgvSeriesReports(model);
        }
        /// <summary>
        /// 初始化数据库
        /// </summary>
Dtos/Request/DebugRequest.cs
@@ -27,7 +27,7 @@
        }
        public class CoverInfo {
            public bool IsCover { set; get; } = true;
            public bool IsCover { set; get; } = false;
        }
    }
}
HH.WCS.Mobox3.DSZSH.csproj
@@ -248,7 +248,7 @@
    <Compile Include="Helpers\ExprHelper.cs" />
    <Compile Include="Helpers\PathHelper.cs" />
    <Compile Include="Helpers\DbHelper.cs" />
    <Compile Include="Models\TN_CNTR_ITEM.cs" />
    <Compile Include="Models\TN_Container_Item.cs" />
    <Compile Include="Models\TN_Check_Detail.cs" />
    <Compile Include="Models\TN_Check_Order.cs" />
    <Compile Include="Models\TN_Inbound_Order.cs" />
Helpers/AgvHelper.cs
@@ -29,7 +29,7 @@
        public static bool IsNextStateOk(int lastState, int nextState) {
            var lastPri = GetPri(lastState);
            var nextPri = GetPri(nextState);
            return lastPri != 0 && nextPri != 0 && lastPri <= nextState;
            return lastPri != 0 && nextPri != 0 && lastPri <= nextPri;
        }
        /// <summary>
Helpers/DbHelper.cs
@@ -52,8 +52,7 @@
                };
                // 配置AOP日志
                //db.Aop.OnLogExecuting = (sql, pars) =>
                //{
                //db.Aop.OnLogExecuting = (sql, pars) => {
                //    Console.WriteLine(sql); // 输出纯SQL语句
                //};
Models/TN_CG_Detail.cs
@@ -6,6 +6,7 @@
    /// </summary>
    [SugarTable("TN_CG_Detail")]
    public class TN_CG_Detail : BaseModel {
        #region 基本属性
        /// <summary>
        /// 料箱商品标识
        /// </summary>
@@ -19,7 +20,7 @@
        /// <summary>
        /// 物料名称
        /// </summary>
        public string S_ITEM_NAME { get; set; } = string.Empty;
        public string S_ITEM_NAME { get; set; } = string.Empty;
        /// <summary>
        /// 容器编码
@@ -44,13 +45,16 @@
        /// <summary>
        /// 货品数量
        /// </summary>
        public int N_QTY { get; set; } = 0;
        public int N_ITEM_NUM { get; set; } = 0;
        /// <summary>
        /// 物料规格
        /// </summary>
        public string S_SPE { get; set; } = string.Empty;
        public string S_ITEM_SPEC { get; set; } = string.Empty;
        #endregion
        #region 拓展
        /// <summary>
        /// 执行标准
        /// </summary>
@@ -66,9 +70,10 @@
        /// </summary>
        public string S_QUALITY_GRADE { get; set; } = string.Empty;
        /// <summary>
        /// 产线号
        /// </summary>
        public int N_PRODUCT_LINE { get; set; } = 0; // NOTE 后续MES可能会提供,先创建
        ///// <summary>
        ///// 产线号
        ///// </summary>
        //public int N_PRODUCT_LINE { get; set; } = 0; // NOTE 后续MES可能会提供,先创建
        #endregion
    }
}
Models/TN_Check_Detail.cs
@@ -13,9 +13,12 @@
    [SugarTable("TN_Check_Detail")]
    public class TN_Check_Detail : BaseModel {
        public string S_NO { get; set; }
        public string S_ITEM_CODE { get; set; }
        //public string S_ITEM_NAME { get; set; }
        public string S_ITEM_NAME { get; set; }
        public string S_LOC_CODE { get; set; }
        public string S_CNTR_CODE { get; set; }
        public string S_BATCH_NO { get; set; }
        public string S_END_AREA { get; set; }
Models/TN_Container_Item.cs
File was renamed from Models/TN_CNTR_ITEM.cs
@@ -10,8 +10,8 @@
    /// <summary>
    /// 容器-物料类型 关系表
    /// </summary>
    [SugarTable("TN_CNTR_ITEM")]
    public class TN_CNTR_ITEM : BaseModel {
    [SugarTable("TN_Container_Item")]
    public class TN_Container_Item : BaseModel {
        public string S_CNTR_CODE { get; set; }
        public string S_ITEM_CODE { get; set; }
    }
Models/TN_Outbound_Detail.cs
@@ -9,7 +9,7 @@
        /// <summary>
        /// 出库单号
        /// </summary>
        public string S_NO { get; set; }
        public string S_OO_NO { get; set; }
        /// <summary>
        /// 业务状态:0等待执行 1已执行待生成任务 2任务执行中 3任务完成
Models/TN_Outbound_Order.cs
@@ -45,7 +45,7 @@
        public bool B_FORCE_OUT { get; set; }
        [Navigate(NavigateType.OneToMany, nameof(TN_Outbound_Detail.S_NO))]
        [Navigate(NavigateType.OneToMany, nameof(TN_Outbound_Detail.S_OO_NO))]
        public List<TN_Outbound_Detail> Details { get; set; }
    }
}
Models/TN_Task.cs
@@ -84,10 +84,10 @@
        public int N_END_LAYER { get; internal set; }
        public int N_CNTR_COUNT { get; internal set; }
        /// <summary>
        /// 是否强制出库:0不强制 1强制
        /// </summary>
        public int N_FORCE { get; set; } = 0;
        ///// <summary>
        ///// 是否强制出库:0不强制 1强制
        ///// </summary>
        //public int N_FORCE { get; set; } = 0;
        internal static string GetStateStr(int state) {
            // 0等待 1已推送 2执行 3完成 4错误
Program.cs
@@ -127,19 +127,14 @@
            {
                List<Task> tasks = new List<Task>();
                //tasks.Add(GetTask(CheckCore.CheckOrderState));
                // 轮询:出库单状态
                tasks.Add(GetTask(OutboundCore.CheckOrderState));
                // 轮询:抽检单状态
                tasks.Add(GetTask(CheckCore.CheckOrderState));
                // 添加任务推送线程
                //tasks.Add(GetTask(WCSCore.Dispatch));
                // 添加自定义线程
                //tasks.Add(GetTask(Monitor.CheckEmptyCnt));//检测空托盘
                // 根据S7/Modbus协议判断输送线的信号  原材料产线库区=>满托缓存库区,空托缓存库区=>原材料产线库区
                //tasks.Add(GetTask(Monitor.CheckS7Devices));
                // 轮询:移库单状态
                tasks.Add(GetTask(ShiftCore.CheckOrderState));
                Task.WaitAll(tasks.ToArray());
            }
ServiceCore/CheckCore.cs
@@ -7,14 +7,15 @@
namespace HH.WCS.Mobox3.DSZSH.ServiceCore {
    public class CheckCore {
        public static void CheckOrderState() {
            var db = DbHelper.GetDbClient();
            try {
                var order = db.Queryable<TN_Check_Order>()
                var order = db.Queryable<TN_Check_Detail>()
                    .Where(c => c.N_B_STATE == SpotStateCode.已执行待生成任务)
                    .OrderBy(c => c.T_CREATE, SqlSugar.OrderByType.Asc).First();
                if (order == null) {
                    LogHelper.Info("暂无待执行的抽检单");
                    LogHelper.Info("轮询--抽检--暂无待执行的Order");
                    return;
                }
@@ -28,16 +29,6 @@
                }
                foreach (var detail in detailList) {
                    var startLocCntrRel = db.Queryable<TN_Location, TN_Loc_Container, TN_CG_Detail>
                        ((l, c, d) => l.S_CODE == c.S_LOC_CODE && c.S_CNTR_CODE == d.S_CNTR_CODE)
                        .Where((l, c, d) => d.S_ITEM_CODE == detail.S_ITEM_CODE && d.S_BATCH_NO == detail.S_BATCH_NO)
                        .Select((l, c) => c) // 选择 LocCntrRel
                        .First(); // 随机抽检,不排序
                    if (startLocCntrRel == null) {
                        LogHelper.Info("没有找到合适的起点货位");
                        continue;
                    }
                    var endLoc = db.Queryable<TN_Location>()
                        .Where(l => l.S_AREA_CODE == detail.S_END_AREA)
@@ -45,7 +36,7 @@
                        .Where(ExprHelper.LocIsEmpty).First();
                    if (endLoc == null) {
                        LogHelper.Info("查询:没有找到合适的终点货位");
                        LogHelper.Info("轮询--抽检:没有找到合适的终点货位!");
                        continue;
                    }
@@ -53,10 +44,10 @@
                        detail.N_B_STATE = SpotStateCode.任务执行中;
                        if (db.Updateable<TN_Check_Detail>(detail).UpdateColumns(it => it.N_B_STATE).ExecuteCommand() <= 0) {
                            tran.RollbackTran();
                            LogHelper.Info($"更新失败:修改抽检单明细表状态为完成");
                            LogHelper.Info($"轮询--抽检:修改抽检单明细表状态为完成--失败!");
                        }
                        if (TaskHelper.LogCreateTask(startLocCntrRel.S_LOC_CODE, startLocCntrRel.S_CNTR_CODE,
                        if (TaskHelper.LogCreateTask(detail.S_LOC_CODE, detail.S_CNTR_CODE,
                            endLoc.S_CODE, TaskName.抽检_出库)) {
                            tran.CommitTran();
                        }
@@ -72,33 +63,45 @@
        }
        public static void UpdateTaskState(int spotStateCode) {
            var db = DbHelper.GetDbClient();
            var detail = db.Queryable<TN_Check_Detail>()
                .First(d => d.N_B_STATE == SpotStateCode.任务执行中);
            if (detail == null) {
                LogHelper.Info("当前没有执行中的抽检单明细项目");
                LogHelper.Info("抽检--AGV任务完成--查询Detail:当前没有 执行中 的Detail表!");
                return;
            }
            using (var tran = db.Ado.UseTran()) {
                detail.N_B_STATE = spotStateCode;
                db.Updateable<TN_Check_Detail>(detail).UpdateColumns(it => it.N_B_STATE).ExecuteCommand();
                if (db.Updateable<TN_Check_Detail>(detail).UpdateColumns(it => it.N_B_STATE).ExecuteCommand() <= 0) {
                    tran.RollbackTran();
                    LogHelper.Info("抽检--AGV任务完成:修改Detail状态 N_B_STATE 为 3任务执行完成 失败!");
                    return;
                }
                if (db.Queryable<TN_Check_Detail>().Count(d => d.S_NO == detail.S_NO && d.N_B_STATE == 2) ==
                    db.Queryable<TN_Check_Detail>().Count(d => d.S_NO == detail.S_NO)) {
                var finishedCount = db.Queryable<TN_Check_Detail>().Count(d => d.S_NO == detail.S_NO && d.N_B_STATE == 3);
                var allCount = db.Queryable<TN_Check_Detail>().Count(d => d.S_NO == detail.S_NO);
                LogHelper.Info($"抽检--AGV任务完成:统计任务已完成:{finishedCount} / {allCount}");
                if (finishedCount == allCount) { // 当前order下的detail,任务都已经完成
                    if (db.Updateable<TN_Check_Order>().SetColumns(it => it.N_B_STATE == SpotStateCode.任务执行完成)
                        .Where(it => it.S_NO == detail.S_NO)
                        .ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        LogHelper.Info("修改Order状态错误");
                        LogHelper.Info("抽检--AGV任务完成--所有任务完成时:修改Order状态 N_B_STATE 为 3任务执行完成 失败!");
                        return;
                    }
                }
                tran.CommitTran();
            }
        }
    }
}
ServiceCore/OutboundCore.cs
@@ -4,6 +4,8 @@
using HH.WCS.Mobox3.DSZSH.Helpers;
using HH.WCS.Mobox3.DSZSH.Models;
using Newtonsoft.Json;
namespace HH.WCS.Mobox3.DSZSH.ServiceCore {
    public class OutboundCore {
        public static void CheckOrderState() {
@@ -14,24 +16,26 @@
                    .OrderBy(c => c.T_CREATE, SqlSugar.OrderByType.Asc).First();
                if (order == null) {
                    LogHelper.Info("轮询:暂无待执行的出库单");
                    LogHelper.Info("轮询--出库--暂无待执行的Order");
                    return;
                }
                if (db.Queryable<TN_Outbound_Detail>()
                    .First(d => d.S_NO == order.S_NO && d.N_B_STATE == SpotStateCode.任务执行中) != null) {
                    LogHelper.Debug("轮询:上一个出库任务仍在进行中");
                var lastDetail = db.Queryable<TN_Outbound_Detail>()
                    .First(d => d.S_OO_NO == order.S_NO && d.N_B_STATE == SpotStateCode.任务执行中);
                if (lastDetail != null) {
                    LogHelper.Info($"轮询--出库--上一个任务仍在进行中:" + JsonConvert.SerializeObject(lastDetail));
                    return;
                }
                var detail = db.Queryable<TN_Outbound_Detail>()
                    .Where(d => d.S_NO == order.S_NO && d.N_B_STATE == SpotStateCode.已执行待生成任务)
                    .Where(d => d.S_OO_NO == order.S_NO && d.N_B_STATE == SpotStateCode.已执行待生成任务)
                    .OrderBy(d => d.T_CREATE, SqlSugar.OrderByType.Asc).First();
                if (detail == null) {
                    //order.N_B_STATE = SpotStateCode.任务执行中;
                    LogHelper.Info("轮询出库:暂无待执行的任务");
                    LogHelper.Info($"轮询--出库--当前Order '{order.S_NO}' 暂无待执行的任务");
                    return;
                }
@@ -40,7 +44,7 @@
                    .First();
                if (startLocCntrRel == null) {
                    LogHelper.Info("轮询:出库:没有找到合适的起点货位");
                    LogHelper.Info($"轮询--出库:没有找到合适的起点货位!");
                    return;
                }
@@ -50,7 +54,7 @@
                    .Where(ExprHelper.LocIsEmpty).First();
                if (endLoc == null) {
                    LogHelper.Info("轮询:出库:没有找到合适的终点货位");
                    LogHelper.Info($"轮询--出库:没有找到合适的终点货位!S_NO为 '{detail.S_OO_NO}',要求Area为 '{detail.S_END_AREA}'");
                    return;
                }
@@ -58,16 +62,15 @@
                    detail.N_B_STATE = SpotStateCode.任务执行中;
                    if (db.Updateable<TN_Outbound_Detail>(detail).UpdateColumns(it => it.N_B_STATE).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        LogHelper.Info($"轮询:出库:更新失败:修改明细表状态为完成");
                        LogHelper.Info($"轮询--出库--修改明细表状态为完成失败!");
                    }
                    if (TaskHelper.LogCreateTask(startLocCntrRel.S_LOC_CODE, startLocCntrRel.S_CNTR_CODE,
                    if (!TaskHelper.LogCreateTask(startLocCntrRel.S_LOC_CODE, startLocCntrRel.S_CNTR_CODE,
                        endLoc.S_CODE, TaskName.成品胶出库)) {
                        tran.CommitTran();
                    }
                    else {
                        tran.RollbackTran();
                    }
                    tran.CommitTran();
                }
            }
            catch (Exception ex) {
@@ -76,28 +79,39 @@
        }
        public static void UpdateTaskState(int spotStateCode) {
            var db = DbHelper.GetDbClient();
            var detail = db.Queryable<TN_Outbound_Detail>()
                    .First(d => d.N_B_STATE == SpotStateCode.任务执行中);
                .First(d => d.N_B_STATE == SpotStateCode.任务执行中);
            if (detail == null) {
                LogHelper.Info("当前没有执行中的出库单明细项目");
                LogHelper.Info("出库--AGV取货--查询Detail:当前没有 执行中 的Detail表!");
                return;
            }
            using (var tran = db.Ado.UseTran()) {
                detail.N_B_STATE = spotStateCode;
                db.Updateable<TN_Outbound_Detail>(detail).UpdateColumns(it => it.N_B_STATE).ExecuteCommand();
                if (db.Updateable<TN_Outbound_Detail>(detail).UpdateColumns(it => it.N_B_STATE).ExecuteCommand() <= 0) {
                    tran.RollbackTran();
                    LogHelper.Info("出库--AGV取货:修改Detail状态 N_B_STATE 为 3任务执行完成 失败!");
                    return;
                }
                if (db.Queryable<TN_Outbound_Detail>().Count(d => d.S_NO == detail.S_NO && d.N_B_STATE == 2) ==
                    db.Queryable<TN_Outbound_Detail>().Count(d => d.S_NO == detail.S_NO)) {
                var finishedCount = db.Queryable<TN_Outbound_Detail>().Count(d => d.S_OO_NO == detail.S_OO_NO && d.N_B_STATE == 3);
                var allCount = db.Queryable<TN_Outbound_Detail>().Count(d => d.S_OO_NO == detail.S_OO_NO);
                    if (db.Updateable<TN_Check_Order>().SetColumns(it => it.N_B_STATE == SpotStateCode.任务执行完成)
                        .Where(it => it.S_NO == detail.S_NO)
                LogHelper.Info($"出库--AGV取货--统计任务已完成:{finishedCount} / {allCount}");
                if (finishedCount == allCount) { // 当前出库单下的所有明细单,任务都已经完成
                    if (db.Updateable<TN_Outbound_Order>().SetColumns(it => it.N_B_STATE == SpotStateCode.任务执行完成)
                        .Where(it => it.S_NO == detail.S_OO_NO)
                        .ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        LogHelper.Info("修改Order状态错误");
                        LogHelper.Info("出库--AGV取货--所有任务完成时:修改Order状态 N_B_STATE 为 3任务执行完成 失败!");
                        return;
                    }
                }
ServiceCore/ShiftCore.cs
@@ -23,13 +23,13 @@
                    .OrderBy(c => c.T_CREATE, SqlSugar.OrderByType.Asc).First();
                if (order == null) {
                    LogHelper.Info("轮询:暂无待执行的移库单");
                    LogHelper.Info("轮询--移库--暂无待执行的Order");
                    return;
                }
                if (db.Queryable<TN_Shift_Detail>()
                    .First(d => d.S_NO == order.S_NO && d.N_B_STATE == SpotStateCode.任务执行中) != null) {
                    LogHelper.Debug("轮询:上一个移库任务仍在进行中");
                    LogHelper.Debug("轮询--移库--上一个任务仍在进行中");
                    return;
                }
@@ -40,7 +40,7 @@
                if (detail == null) {
                    //order.N_B_STATE = SpotStateCode.任务执行中;
                    LogHelper.Info("轮询移库:暂无待执行的任务");
                    LogHelper.Info("轮询--移库--暂无待执行的任务");
                    return;
                }
@@ -49,7 +49,7 @@
                    .First();
                if (startLocCntrRel == null) {
                    LogHelper.Info("轮询:移库:没有找到合适的起点货位");
                    LogHelper.Info("轮询--移库:没有找到合适的起点货位!");
                    return;
                }
@@ -59,7 +59,7 @@
                    .Where(ExprHelper.LocIsEmpty).First();
                if (endLoc == null) {
                    LogHelper.Info("轮询:出库:没有找到合适的终点货位");
                    LogHelper.Info("轮询--出库:没有找到合适的终点货位!");
                    return;
                }
@@ -67,16 +67,15 @@
                    detail.N_B_STATE = SpotStateCode.任务执行中;
                    if (db.Updateable<TN_Shift_Detail>(detail).UpdateColumns(it => it.N_B_STATE).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        LogHelper.Info($"轮询:出库:更新失败:修改明细表状态为完成");
                        LogHelper.Info($"轮询--出库:修改明细表状态为完成--失败!");
                    }
                    if (TaskHelper.LogCreateTask(startLocCntrRel.S_LOC_CODE, startLocCntrRel.S_CNTR_CODE,
                    if (!TaskHelper.LogCreateTask(startLocCntrRel.S_LOC_CODE, startLocCntrRel.S_CNTR_CODE,
                        endLoc.S_CODE, TaskName.成品胶出库)) {
                        tran.CommitTran();
                    }
                    else {
                        tran.RollbackTran();
                    }
                    tran.CommitTran();
                }
            }
            catch (Exception ex) {
@@ -85,28 +84,39 @@
        }
        public static void UpdateTaskState(int spotStateCode) {
            var db = DbHelper.GetDbClient();
            var detail = db.Queryable<TN_Shift_Detail>()
                .First(d => d.N_B_STATE == SpotStateCode.任务执行中);
            if (detail == null) {
                LogHelper.Info("当前没有执行中的移库单明细项目");
                LogHelper.Info("移库--AGV任务完成--查询Detail:当前没有 执行中 的Detail表!");
                return;
            }
            using (var tran = db.Ado.UseTran()) {
                detail.N_B_STATE = spotStateCode;
                db.Updateable<TN_Shift_Detail>(detail).UpdateColumns(it => it.N_B_STATE).ExecuteCommand();
                if (db.Updateable<TN_Shift_Detail>(detail).UpdateColumns(it => it.N_B_STATE).ExecuteCommand() <= 0) {
                    tran.RollbackTran();
                    LogHelper.Info("移库--AGV任务完成:修改Detail状态 N_B_STATE 为 3任务执行完成 失败!");
                    return;
                }
                if (db.Queryable<TN_Shift_Detail>().Count(d => d.S_NO == detail.S_NO && d.N_B_STATE == 2) ==
                    db.Queryable<TN_Shift_Detail>().Count(d => d.S_NO == detail.S_NO)) {
                var finishedCount = db.Queryable<TN_Shift_Detail>().Count(d => d.S_NO == detail.S_NO && d.N_B_STATE == 3);
                var allCount = db.Queryable<TN_Shift_Detail>().Count(d => d.S_NO == detail.S_NO);
                LogHelper.Info($"移库--AGV任务完成:统计任务已完成:{finishedCount} / {allCount}");
                if (finishedCount == allCount) { // 当前order下的detail,任务都已经完成
                    if (db.Updateable<TN_Shift_Order>().SetColumns(it => it.N_B_STATE == SpotStateCode.任务执行完成)
                        .Where(it => it.S_NO == detail.S_NO)
                        .ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        LogHelper.Info("修改Order状态错误");
                        LogHelper.Info("移库--AGV任务完成--所有任务完成时:修改Order状态 N_B_STATE 为 3任务执行完成 失败!");
                        return;
                    }
                }
Services/DebugService.cs
@@ -80,35 +80,37 @@
        /// 初始数据库建立
        /// </summary>
        /// <returns></returns>
        public static string CreateDatabase(bool cover = true) {
        public static string CreateDatabase(bool cover = false) {
            try {
                var db = DbHelper.GetDbClient();
                var entityTypes = new Type[] { 
                    typeof(TN_CAR_IN),
                    typeof(TN_CG_Detail),
                    typeof(TN_Container),
                    typeof(TN_Loc_Container),
                    typeof(TN_Location),
                    typeof(TN_Task),
                    typeof(TN_Task_Action),
                    typeof(SysHelper.OI_SYS_MAXID),
                    //typeof(TN_CAR_IN),
                    //typeof(TN_CG_Detail),
                    //typeof(TN_Container),
                    //typeof(TN_Loc_Container),
                    //typeof(TN_Location),
                    //typeof(TN_Task),
                    //typeof(TN_Task_Action),
                    //typeof(SysHelper.OI_SYS_MAXID),
                    typeof(TN_Inbound_Order),
                    //typeof(TN_Inbound_Order),
                    typeof(TN_Check_Detail),
                    typeof(TN_Check_Order),
                    typeof(TN_CNTR_ITEM),
                    typeof(TN_Outbound_Detail),
                    typeof(TN_Outbound_Order),
                    //typeof(TN_Check_Order),
                    //typeof(TN_CNTR_ITEM),
                    //typeof(TN_Outbound_Detail),
                    //typeof(TN_Outbound_Order),
                    //typeof(TN_Shift_Order),
                    //typeof(TN_Shift_Detail)
                };
                using (var tran = db.Ado.UseTran()) {
                    if (cover) {
                        // 删除所有表(按依赖关系倒序)
                        var tables = db.DbMaintenance.GetTableInfoList();
                        foreach (var table in tables.OrderByDescending(t => t.Name)) {
                            db.DbMaintenance.DropTable(table.Name);
                        }
                        //var tables = db.DbMaintenance.GetTableInfoList();
                        //foreach (var table in tables.OrderByDescending(t => t.Name)) {
                        //    db.DbMaintenance.DropTable(table.Name);
                        //}
                        // 创建新表
                        db.CodeFirst.InitTables(entityTypes);
Services/MoboxService.cs
@@ -3,6 +3,7 @@
using System.Linq;
using HH.WCS.Mobox3.DSZSH.Consts;
using HH.WCS.Mobox3.DSZSH.Dispatch;
using HH.WCS.Mobox3.DSZSH.Helper;
using HH.WCS.Mobox3.DSZSH.Helpers;
using HH.WCS.Mobox3.DSZSH.Models;
@@ -371,11 +372,13 @@
        public static SimpleResult CreateCheckOrder(CreateCheckOrderInfo model) {
            var db = DbHelper.GetDbClient();
            try {
                var orderNo = GenerateOrderNo("抽检单号", "CN");
                // 绑定操作:插入出库单、所有的出库单明细
                using (var tran = db.Ado.UseTran()) {
                    var order = new TN_Check_Order {
                        S_NO = GenerateOrderNo("抽检单号", "CN"),
                        S_NO = orderNo,
                        S_ITEM_CODE = model.ItemCode,
                        //S_ITEM_NAME = model.ItemName,
                        S_BATCH_NO = model.BatchNo,
@@ -388,20 +391,33 @@
                        return BuildSimpleResult(2, "生成 抽检单 失败:" + JsonConvert.SerializeObject(order));
                    }
                    for (int i = 0; i < model.Qty; i++) {
                        var detail = new TN_Check_Detail {
                            S_NO = order.S_NO,
                            S_ITEM_CODE = model.ItemCode,
                            S_BATCH_NO = model.BatchNo,
                            S_END_AREA = model.EndArea
                        };
                    var cgDetailList = SelectCgByTotalQty(model);
                        if (db.Insertable<TN_Check_Detail>(detail).ExecuteCommand() <= 0) {
                            tran.RollbackTran();
                            return BuildSimpleResult(3, "生成 抽检单明细 失败:" + JsonConvert.SerializeObject(detail));
                        }
                    if (cgDetailList.Count == 0) {
                        return BuildSimpleResult(3, "没有合适的物料可以抽检");
                    }
                    foreach (var cgDetail in cgDetailList) {
                        var detail = new TN_Outbound_Detail {
                            S_OO_NO = orderNo,
                            S_ITEM_CODE = cgDetail.S_ITEM_CODE,
                            S_BATCH_NO = cgDetail.S_BATCH_NO,
                            S_CNTR_CODE = cgDetail.S_CNTR_CODE,
                            S_END_AREA = model.EndArea,
                        };
                        cgDetail.N_ITEM_STATE = 3;
                        cgDetail.S_ITEM_STATE = "正在检验";
                        if (db.Insertable<TN_Outbound_Detail>(detail).ExecuteCommand() <= 0
                            && db.Updateable<TN_CG_Detail>(cgDetail).UpdateColumns(it => new { it.N_ITEM_STATE, it.S_ITEM_STATE }).ExecuteCommand() <= 0) {
                            tran.RollbackTran();
                            return BuildSimpleResult(4, "生成出库单明细失败:" + JsonConvert.SerializeObject(detail));
                        }
                        LogHelper.Debug("创建出库单明细成功:" + JsonConvert.SerializeObject(detail));
                    }
                    tran.CommitTran();
                }
                return BuildSimpleResult(0, $"创建 抽检单 成功");
@@ -556,6 +572,56 @@
            }
        }
        public static List<TN_CG_Detail> SelectCgByTotalQty(CreateCheckOrderInfo model) {
            var db = DbHelper.GetDbClient();
            var result = new List<TN_CG_Detail>();
            var targetNum = model.Qty;
            try {
                var targetCg = db.Queryable<TN_CG_Detail>().Where(a => a.S_ITEM_CODE == model.ItemCode
                && a.N_ITEM_NUM > targetNum).
                OrderBy(a => a.N_ITEM_NUM, OrderByType.Asc).First();
                if (targetCg != null) //刚好有一行满足条件
                {
                    result.Add(targetCg);
                    return result;
                }
                var sortedMaterials = new List<TN_CG_Detail>();
                sortedMaterials = db.Queryable<TN_CG_Detail, TN_Loc_Container>((d, c) => d.S_CNTR_CODE == c.S_CNTR_CODE)
                    .Where(d => d.S_ITEM_CODE == model.ItemCode && d.S_BATCH_NO == model.BatchNo && d.N_ITEM_NUM > 0)
                    .Where((d, c) => c.S_CNTR_TYPE == model.CntrType)
                    .Where(d => d.N_ITEM_STATE == 1 && d.S_ITEM_STATE == "待检")
                    .OrderBy(d => d.N_ITEM_NUM, OrderByType.Desc)
                    .OrderBy(d => d.N_ITEM_STATE, OrderByType.Asc).ToList();
                if (sortedMaterials.Count == 0) //没有满足条件的
                {
                    return result;
                }
                int countNum = 0;
                foreach (var mat in sortedMaterials) {
                    countNum += mat.N_ITEM_NUM;
                    result.Add(mat);
                    if (countNum >= targetNum) {
                        break;
                    }
                }
                if (result.Sum(a => a.N_ITEM_NUM) >= targetNum) {
                    return result;
                }
                else {
                    result.Clear();
                    return result;
                }
            }
            catch (Exception ex) {
                throw ex;
            }
        }
        #endregion
        #region Mobox 功能
@@ -584,14 +650,13 @@
                        return BuildSimpleResult(3, "没有合适的物料可以出库");
                    }
                    // NOTE 如果创建order的时候就指定具体出库物料的cntr,那么如果在创建任务前,这个物料被错误抽检了怎么办
                    foreach (var cgDetail in cgDetailList) {
                        var detail = new TN_Outbound_Detail {
                            S_NO = orderNo,
                            S_OO_NO = orderNo,
                            S_ITEM_CODE = cgDetail.S_ITEM_CODE,
                            S_BATCH_NO = cgDetail.S_BATCH_NO,
                            S_CNTR_CODE = cgDetail.S_CNTR_CODE,
                            N_COUNT = cgDetail.N_QTY,
                            N_COUNT = cgDetail.N_ITEM_NUM,
                            S_END_AREA = model.EndArea
                        };
@@ -646,10 +711,9 @@
                        return BuildSimpleResult(3, "没有合适的物料可以出库");
                    }
                    // NOTE 如果创建order的时候就指定具体出库物料的cntr,那么如果在创建任务前,这个物料被错误抽检了怎么办
                    foreach (var cgDetail in cgDetailList) {
                        var detail = new TN_Outbound_Detail {
                            S_NO = orderNo,
                            S_OO_NO = orderNo,
                            S_ITEM_CODE = cgDetail.S_ITEM_CODE,
                            S_BATCH_NO = cgDetail.S_BATCH_NO,
                            S_CNTR_CODE = cgDetail.S_CNTR_CODE,
@@ -693,8 +757,8 @@
            try {
                var targetCg = db.Queryable<TN_CG_Detail>().Where(a => a.S_ITEM_CODE == model.ItemCode
                && a.N_QTY > targetNum).
                OrderBy(a => a.N_QTY, OrderByType.Asc).First();
                && a.N_ITEM_NUM > targetNum).
                OrderBy(a => a.N_ITEM_NUM, OrderByType.Asc).First();
                if (targetCg != null) //刚好有一行满足条件
                {
                    result.Add(targetCg);
@@ -702,29 +766,42 @@
                }
                // NOTE 根据总量选detail时,是否需要考虑货位的高低?
                var sortedMaterials = db.Queryable<TN_CG_Detail, TN_Loc_Container>((d, c) => d.S_CNTR_CODE == c.S_CNTR_CODE)
                    .Where(d => d.S_ITEM_CODE == model.ItemCode && d.S_BATCH_NO == model.BatchNo && d.N_QTY > 0)
                var sortedMaterials = new List<TN_CG_Detail>();
                if (model.ForcedOut) {
                    sortedMaterials = db.Queryable<TN_CG_Detail, TN_Loc_Container>((d, c) => d.S_CNTR_CODE == c.S_CNTR_CODE)
                    .Where(d => d.S_ITEM_CODE == model.ItemCode && d.S_BATCH_NO == model.BatchNo && d.N_ITEM_NUM > 0)
                    .Where((d, c) => c.S_CNTR_TYPE == model.CntrType)
                    .Where(d => (model.ForcedOut && d.N_ITEM_STATE == 0 && d.S_ITEM_STATE == "合格")
                        || (!model.ForcedOut && (d.N_ITEM_STATE == 0 && d.S_ITEM_STATE == "合格"
                        || d.N_ITEM_STATE == 1 && d.S_ITEM_STATE == "待检")))
                    .OrderBy(d => d.N_QTY, OrderByType.Desc)
                    .Where(d => d.N_ITEM_STATE == 0 && d.S_ITEM_STATE == "合格"
                             || d.N_ITEM_STATE == 1 && d.S_ITEM_STATE == "待检")
                    .OrderBy(d => d.N_ITEM_NUM, OrderByType.Desc)
                    .OrderBy(d => d.N_ITEM_STATE, OrderByType.Asc).ToList();
                }
                else {
                    sortedMaterials = db.Queryable<TN_CG_Detail, TN_Loc_Container>((d, c) => d.S_CNTR_CODE == c.S_CNTR_CODE)
                    .Where(d => d.S_ITEM_CODE == model.ItemCode && d.S_BATCH_NO == model.BatchNo && d.N_ITEM_NUM > 0)
                    .Where((d, c) => c.S_CNTR_TYPE == model.CntrType)
                    .Where(d => d.N_ITEM_STATE == 0 && d.S_ITEM_STATE == "合格")
                    .OrderBy(d => d.N_ITEM_NUM, OrderByType.Desc)
                    .OrderBy(d => d.N_ITEM_STATE, OrderByType.Asc).ToList();
                }
                if (sortedMaterials.Count == 0) //没有满足条件的
                {
                    return result;
                }
                float countNum = 0;
                int countNum = 0;
                foreach (var mat in sortedMaterials) {
                    countNum += mat.N_QTY;
                    countNum += mat.N_ITEM_NUM;
                    result.Add(mat);
                    if (countNum >= targetNum) {
                        break;
                    }
                }
                if (result.Sum(a => a.N_QTY) >= targetNum) {
                if (result.Sum(a => a.N_ITEM_NUM) >= targetNum) {
                    return result;
                }
                else {
Services/WmsService.cs
@@ -33,7 +33,7 @@
                    S_STANDARD = model.Standard,
                    S_NET_WEIGHT = model.NetWeight,
                    S_QUALITY_GRADE = model.QualityGrade,
                    N_PRODUCT_LINE = random.Next(0, 3), // NOTE 产线号:目前随机(后期可能会指定,或者PDA绑定时再填入)
                    //N_PRODUCT_LINE = random.Next(0, 3), // NOTE 产线号:目前随机(后期可能会指定,或者PDA绑定时再填入)
                };
                // 货位容器绑定的逻辑,在好运箱下线PDA的流程中操作