kazelee
2025-05-19 b079910e5de15863c26e479ffab15cc45d706f1a
ServiceCore/OutboundCore.cs
@@ -1,83 +1,73 @@
using System;
using System.Collections.Generic;
using System.Linq;
using HH.WCS.Mobox3.DSZSH.Consts;
using HH.WCS.Mobox3.DSZSH.Helpers;
using HH.WCS.Mobox3.DSZSH.Helpers.Model;
using HH.WCS.Mobox3.DSZSH.Models;
using Newtonsoft.Json;
namespace HH.WCS.Mobox3.DSZSH.ServiceCore {
    /// <summary>
    /// 定时轮询任务:出库业务核心
    /// </summary>
    public class OutboundCore {
        /// <summary>
        /// 后台轮询出库单/出库明细单,生成出库任务表
        /// </summary>
        public static void CheckOutboundOrder() {
        public static void CheckOrderState() {
            var db = DbHelper.GetDbClient();
            try {
                // 查找所有的 等待出库 的 出库单,按 先创建先处理 排序
                var orders = db.Queryable<TN_Outbound_Order>()
                    .Where(o => o.N_B_STATE == 0)
                    .OrderBy(o => o.T_CREATE)
                    .Mapper(
                        o => o.Details, // 将子表数据映射到主表的 Details 属性
                        o => o.S_NO,    // 主表关联字段
                        d => d.S_NO     // 子表关联字段
                    )
                    .ToList();
                var order = db.Queryable<TN_Outbound_Order>()
                    .Where(c => c.N_B_STATE == SpotStateCode.已执行待生成任务)
                    .OrderBy(c => c.T_CREATE, SqlSugar.OrderByType.Asc).First();
                if (orders.Count == 0) {
                    LogHelper.Info("轮询 | 当前没有等待执行的出库单");
                if (order == null) {
                    LogHelper.Info("轮询--出库--暂无待执行的Order");
                    return;
                }
                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_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($"轮询--出库--当前Order '{order.S_NO}' 暂无待执行的任务");
                    return;
                }
                var startLocCntrRel = db.Queryable<TN_Loc_Container>()
                    .Where(c => c.S_CNTR_CODE == detail.S_CNTR_CODE)
                    .First();
                if (startLocCntrRel == null) {
                    LogHelper.Info($"轮询--出库:没有找到合适的起点货位!");
                    return;
                }
                var endLoc = db.Queryable<TN_Location>()
                    .Where(l => l.S_AREA_CODE == detail.S_END_AREA)
                    .Where(ExprHelper.LocIsFree)
                    .Where(ExprHelper.LocIsEmpty).First();
                if (endLoc == null) {
                    LogHelper.Info($"轮询--出库:没有找到合适的终点货位!S_NO为 '{detail.S_OO_NO}',要求Area为 '{detail.S_END_AREA}'");
                    return;
                }
                using (var tran = db.Ado.UseTran()) {
                    detail.N_B_STATE = SpotStateCode.任务执行中;
                    if (db.Updateable<TN_Outbound_Detail>(detail).UpdateColumns(it => it.N_B_STATE).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        LogHelper.Info($"轮询--出库--修改明细表状态为完成失败!");
                    }
                    foreach (var o in orders) {
                        foreach (var d in o.Details) {
                            for (int i = 0; i < d.N_QTY; i++) {
                                var task = new TN_Outbound_Task {
                                    S_CG_ID = d.S_CG_ID,
                                    S_END_AREA = d.S_END_AREA,
                                    N_FORCE = o.N_FORCE,
                                    S_BATCH_NO = d.S_BATCH_NO,
                                    N_STATE = 0
                                };
                                if (db.Insertable<TN_Outbound_Task>(task).ExecuteCommand() <= 0) {
                                    tran.RollbackTran();
                                    LogHelper.Info("插入任务出错");
                                    return;
                                }
                            }
                            d.N_B_STATE = 1;
                            if (db.Updateable<TN_Outbound_Detail>(d).UpdateColumns(c => c.N_B_STATE).ExecuteCommand() > 0) {
                                LogHelper.Info("更新 N_B_STATE 成功");
                            }
                            else {
                                tran.RollbackTran();
                                LogHelper.Info("更新 N_B_STATE 失败");
                                return;
                            }
                        }
                        o.N_B_STATE = 1;
                        if (db.Updateable<TN_Outbound_Order>(o).UpdateColumns(c => c.N_B_STATE).ExecuteCommand() > 0) {
                            LogHelper.Info("更新 N_B_STATE 成功");
                        }
                        else {
                            tran.RollbackTran();
                            LogHelper.Info("更新 N_B_STATE 失败");
                            return;
                        }
                    if (!TaskHelper.LogCreateTask(startLocCntrRel.S_LOC_CODE, startLocCntrRel.S_CNTR_CODE,
                        endLoc.S_CODE, TaskName.成品胶出库)) {
                        tran.RollbackTran();
                    }
                    tran.CommitTran();
@@ -85,87 +75,48 @@
            }
            catch (Exception ex) {
                LogHelper.InfoEx(ex);
                throw;
            }
        }
        /// <summary>
        /// 轮询出库
        /// </summary>
        public static void CheckOutboundTask() {
        public static void UpdateTaskState(int spotStateCode) {
            var db = DbHelper.GetDbClient();
            try {
                var task = db.Queryable<TN_Outbound_Task>()
                    .Where(t => t.N_STATE == 0).First();
            var detail = db.Queryable<TN_Outbound_Detail>()
                .First(d => d.N_B_STATE == SpotStateCode.任务执行中);
                if (task == null) {
                    LogHelper.Info("轮询 | 出库任务队列 暂无待执行的任务");
            if (detail == null) {
                LogHelper.Info("出库--AGV取货--查询Detail:当前没有 执行中 的Detail表!");
                return;
            }
            using (var tran = db.Ado.UseTran()) {
                detail.N_B_STATE = spotStateCode;
                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;
                }
                var headTask = task;
                if (headTask.N_STATE != 0) {
                    LogHelper.Info("轮询 | 出库任务队列 队头任务尚未完成");
                    return;
                }
                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);
                var locCntr = 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_CG_ID == headTask.S_CG_ID && d.S_BATCH_NO == headTask.S_BATCH_NO)
                    // 如果不是强制出库,物料状态必须必须合格
                    // 否则,只要不是正在检验的物料即可
                    .Where((l, c, d) => (headTask.N_FORCE == 0 && d.N_ITEM_STATE == 0 && d.S_ITEM_STATE == "合格")
                        || (headTask.N_FORCE != 0 && d.N_ITEM_STATE != 3 && d.S_ITEM_STATE != "正在检验"))
                    // 物料状态对应的数字,越小越优先
                    .OrderBy((l, c, d) => d.N_ITEM_STATE)
                    .OrderBy(l => l.N_LAYER)
                    .Select((l, c) => new { Location = l, Container = c }).First();
                if (locCntr == null) {
                    LogHelper.Info("轮询 | 不存在符合条件的物料货位");
                    return;
                }
                LogHelper.Info($"出库--AGV取货--统计任务已完成:{finishedCount} / {allCount}");
                var endLoc = db.Queryable<TN_Location>()
                    .Where(l => l.S_AREA_CODE == headTask.S_END_AREA)
                    .Where(ExprHelper.LocIsFree)
                    .Where(ExprHelper.LocIsEmpty)
                    .OrderBy(l => l.S_CODE)
                    .First();
                if (finishedCount == allCount) { // 当前出库单下的所有明细单,任务都已经完成
                if (endLoc == null) {
                    LogHelper.Info("轮询 | 不存在符合条件的出库终点库位");
                    return;
                }
                    if (db.Updateable<TN_Outbound_Order>().SetColumns(it => it.N_B_STATE == SpotStateCode.任务执行完成)
                        .Where(it => it.S_NO == detail.S_OO_NO)
                        .ExecuteCommand() <= 0) {
                using (var tran = db.Ado.UseTran()) {
                    if (TaskHelper.LogCreateTask(locCntr.Location.S_CODE, locCntr.Container.S_CNTR_CODE, endLoc.S_CODE, TaskName.成品胶出库)) {
                        task.N_STATE = 1;
                        if (db.Updateable<TN_Outbound_Task>(task).UpdateColumns(c => c.N_STATE).ExecuteCommand() <= 0) {
                            tran.RollbackTran();
                            LogHelper.Info("修改出库任务状态错误");
                        }
                        else {
                            tran.CommitTran();
                            LogHelper.Info("修改出库任务状态成功");
                        }
                        tran.RollbackTran();
                        LogHelper.Info("出库--AGV取货--所有任务完成时:修改Order状态 N_B_STATE 为 3任务执行完成 失败!");
                        return;
                    }
                }
            }
            catch (Exception ex) {
                LogHelper.InfoEx(ex);
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="state"></param>
        public static void UpdateTaskState(int state = 2) {
                tran.CommitTran();
            }
        }
    }