kazelee
2025-05-20 ef839d119eec2c28fac5f5ba175d71f926afae44
Services/MoboxService.cs
@@ -1,14 +1,16 @@
using HH.WCS.Mobox3.AnGang.AppStart;
using HH.WCS.Mobox3.AnGang.config;
using System;
using HH.WCS.Mobox3.AnGang.AppStart;
using HH.WCS.Mobox3.AnGang.Consts;
using HH.WCS.Mobox3.AnGang.Helper;
using HH.WCS.Mobox3.AnGang.Helpers;
using HH.WCS.Mobox3.AnGang.Models;
using Newtonsoft.Json;
using System;
using static HH.WCS.Mobox3.AnGang.Dtos.Request.ErpRequest;
using static HH.WCS.Mobox3.AnGang.Dtos.Request.MoboxRequest;
using static HH.WCS.Mobox3.AnGang.Dtos.Response.MoboxResponse;
using static HH.WCS.Mobox3.AnGang.Helpers.ResultHelper;
namespace HH.WCS.Mobox3.AnGang.Services {
    public class MoboxService {
@@ -18,26 +20,21 @@
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult InWarehouse(InWarehouseInfo model) {
        internal static SimpleResult Inbound(InboundInfo model) {
            LogHelper.Info("触发API:产品入库(PDA)" + JsonConvert.SerializeObject(model), "API");
            var db = DbHelper.GetDbClient();
            var startLoc = new TN_Location();
            //var endLoc = new TN_Location();
            try {
                // 起点位置必须:为空、无锁、启用、属于收发区域
                startLoc = db.Queryable<TN_Location>().
                    First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_SHELF_CODE == AreaCode.收发货位区);
                    First(a => a.S_CODE == model.StartLoc
                    && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y"
                    && a.S_AREA_CODE == AreaCode.收发区);
                if (startLoc == null) {
                    return BuildSimpleResult(1, $"起点位置{model.startLoc}不存在!");
                    return BuildSimpleResult(1, $"起点位置{model.StartLoc}不存在!");
                }
                //if (!LocationHelper.IsStartLocationTransferOk(model.startLoc,
                //    a => a.S_SHELF_CODE == Settings.Areas[0],
                //    out startLoc)) {
                //    return BuildSimpleResult(1, $"起点位置{model.startLoc}不存在!");
                //}
                // 容器 ID 和 物料 ID 未指定,由系统直接生成
                var cntID = Guid.NewGuid().ToString("D");
@@ -53,14 +50,17 @@
                    S_CNTR_CODE = cntID,
                };
                var endArea = ""; // 默认终点区域为空
                var endLoc = "0"; // 假的默认终点地址
                // 指定货位排号(不能为空、空字符串或空格)
                if (model.endShelf != null && model.endShelf.Trim() != "") {
                    endArea = model.endShelf;
                    // 没有在配置文件找到这个货架号
                    if (!Settings.AreaMap[AreaName.货架区].Contains(endArea)) {
                        return BuildSimpleResult(2, $"货架号 {model.endShelf} 不存在");
                if (model.Row != null && model.Row.Trim() != "") {
                    endLoc = model.Row; // 用排号字符串当做假地址
                    if (!int.TryParse(model.Row.Trim(), out int row)) {
                        return BuildSimpleResult(2, $"{model.Row} 不合法:无法转成整数类型");
                    }
                    // 货架排号只能是 0 - 8
                    if (row <= 0 || row > 8) {
                        return BuildSimpleResult(2, $"货架号 {model.Row} 必须是1-8之间的整数");
                    }
                }
@@ -69,19 +69,19 @@
                    if (db.Insertable<TN_Loc_Container>(cntLoc).ExecuteCommand() > 0
                        && db.Insertable<TN_CG_Detail>(cgCnt).ExecuteCommand() > 0) {
                        //创建产品入库任务:创建搬送任务,起点终点容器
                        if (WCSHelper.CreateTaskWithArea(startLoc.S_CODE, endArea, "产品入库(PDA)", 3, cntID)) {
                        if (WCSHelper.CreateTask(startLoc.S_CODE, endLoc, TaskName.产品入库, 3, cntID)) {
                            //如果操作TN_Location会造成死锁
                            LocationHelper.LockLoc(startLoc.S_CODE, 2);//起点出库锁,
                            //LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                            trans.CommitTran();
                            return BuildSimpleResult(0, $"生成 产品入库(PDA) 成功,容器号 {cntID} ,起点 {startLoc.S_CODE} ,终点货架 {endArea} ,终点货位未指定");
                            return BuildSimpleResult(0, $"生成 产品入库 成功,容器号 {cntID} ,起点 {startLoc.S_CODE} ,终点货架 {endLoc} ,终点货位未指定");
                        }
                        else {
                            trans.RollbackTran();
                            return BuildSimpleResult(5, $"生成 产品入库(PDA) 失败,容器号 {cntID} ,起点 {startLoc.S_CODE} ,终点货架 {endArea} ,终点货位未指定");
                            return BuildSimpleResult(5, $"生成 产品入库 失败,容器号 {cntID} ,起点 {startLoc.S_CODE} ,终点货架 {endLoc} ,终点货位未指定");
                        }
                    }
                    else {
@@ -105,36 +105,50 @@
            try {
                // 任务号存在:终点货架和终点位置为空,且任务为产品入库(PDA)
                //var task = db.Queryable<TN_Task>().First(a => a.S_CODE == model.taskNo && a.S_END_AREA == "" && a.S_END_LOC == "" && a.S_TYPE == "产品入库(PDA)");
                var task = db.Queryable<TN_Task>().First(a => a.S_EQ_NO == model.forklift_no && a.S_END_AREA == "" && a.S_END_LOC == "" && a.S_TYPE == "产品入库(PDA)");
                //var task = db.Queryable<TN_Task>().First(a => a.S_EQ_NO == model.forklift_no && a.S_END_AREA == "HJQ" && a.S_END_LOC == "0" && a.S_TYPE == "产品入库(PDA)");
                var task = db.Queryable<TN_Task>()
                    .Where(a => a.S_B_STATE == "取货完成" && a.S_TYPE == TaskName.产品入库)
                    .OrderBy(a => a.T_CREATE, SqlSugar.OrderByType.Desc).First();
                
                if (task == null) {
                    //return BuildSimpleResult(2, $"任务号 {model.taskNo} 不存在,或不满足终点货架为空、终点位置为空且为 产品入库(PDA) 任务");
                    return BuildSimpleResult(2, $"小车 '{model.forklift_no}' 当前不存在任务,或不满足终点货架为空、终点位置为空且为 产品入库(PDA) 任务");
                    return BuildSimpleResult(2, $"当前不存在状态为 取货完成 的 产品入库 任务");
                }
                if (task.S_END_LOC != null && task.S_END_LOC != "0") {
                    return BuildSimpleResult(3, $"该任务已有终点");
                }
                var cgDetail = db.Queryable<TN_CG_Detail>()
                    .Where(a => a.S_CNTR_CODE == task.S_CNTR_CODE).First();
                if (cgDetail == null) {
                    return BuildSimpleResult(4, $"托盘物料不存在");
                }
                var endLoc = new TN_Location();
                if (task.F_WEIGHT > 1500) {
                if (cgDetail.F_QTY > 1500) {
                    // 重量超过1.5t,需要选择1-3层货架
                    endLoc = db.Queryable<TN_Location>().First(
                        a => a.S_CODE == model.endLoc && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.N_CURRENT_NUM == 0 && a.N_HEIGHT <= 3);
                        a => a.S_CODE == model.endLoc && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.N_CURRENT_NUM == 0 && a.N_LAYER <= 3 && a.S_AREA_CODE == AreaCode.货架区);
                }
                else if (cgDetail.F_QTY > 0) {
                    endLoc = db.Queryable<TN_Location>().First(
                        a => a.S_CODE == model.endLoc && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.N_CURRENT_NUM == 0 && a.S_AREA_CODE == AreaCode.货架区);
                }
                else {
                    endLoc = db.Queryable<TN_Location>().First(
                        a => a.S_CODE == model.endLoc && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.N_CURRENT_NUM == 0);
                    return BuildSimpleResult(5, $"物料重量信息不合法:{cgDetail.F_QTY}");
                }
                // 没有符合条件的货位
                if (endLoc == null) {
                    return BuildSimpleResult(3, $"货位{model.endLoc}不满足要求:不存在或不满足称重放置要求");
                    return BuildSimpleResult(6, $"货位{model.endLoc}不存在,或不满足称重放置要求");
                }
                // 修改任务终点为PDA指定终点
                task.S_END_LOC = endLoc.S_CODE;
                task.S_END_AREA = endLoc.S_SHELF_CODE;
                using (var trans = db.Ado.UseTran()) {
                    if (db.Updateable<TN_Task>(task).ExecuteCommand() > 0) {
                    if (db.Updateable<TN_Task>(task).UpdateColumns(a => a.S_END_LOC).ExecuteCommand() > 0) {
                        LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                        trans.CommitTran();
@@ -143,7 +157,7 @@
                    else {
                        trans.RollbackTran();
                        return BuildSimpleResult(4, $"任务{task.S_CODE}修改失败,修改终点位置为{endLoc.S_CODE}");
                        return BuildSimpleResult(7, $"任务{task.S_CODE}修改失败,修改终点位置为{endLoc.S_CODE}");
                    }
                }
            }
@@ -157,7 +171,7 @@
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult PartOutWarehouse(PartOutWarehouseInfo model) {
        internal static SimpleResult PartOutbound(PartOutboundInfo model) {
            LogHelper.Info("触发API:产品部分出库(WMS)" + JsonConvert.SerializeObject(model), "API");
            var db = DbHelper.GetDbClient();
@@ -175,7 +189,7 @@
                    return BuildSimpleResult(3, $"起点位置 {model.startLoc} 没有绑定容器,无可出库的物料");
                }
                var endLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.endLoc && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == AreaCode.收发货位区);
                var endLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.endLoc && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == AreaCode.收发区);
                if (endLoc == null) {
                    return BuildSimpleResult(4, $"终点位置 {model.endLoc} 不具备放货条件");
@@ -183,17 +197,17 @@
                using (var trans = db.Ado.UseTran()) {
                    // 解绑:起点货位与待搬运容器(不需要手动deleteable操作,内部会自动操作的)
                    if (WCSHelper.CreateTask(startLoc.S_CODE, endLoc.S_CODE, "产品部分出库(WMS)", 3, locCtnrRel.S_CNTR_CODE))//创建搬送任务,起点终点容器
                    if (WCSHelper.CreateTask(startLoc.S_CODE, endLoc.S_CODE, TaskName.产品部分出库, 3, locCtnrRel.S_CNTR_CODE))//创建搬送任务,起点终点容器
                        {//如果操作TN_Location会造成死锁
                        LocationHelper.LockLoc(startLoc.S_CODE, 2);//起点出库锁,
                        LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                        trans.CommitTran();
                        return BuildSimpleResult(0, $"生成 产品出库(WMS) 成功,容器号{locCtnrRel.S_CNTR_CODE},起点{startLoc.S_CODE},终点{endLoc.S_CODE}");
                        return BuildSimpleResult(0, $"生成 产品部分出库 成功,容器号{locCtnrRel.S_CNTR_CODE},起点{startLoc.S_CODE},终点{endLoc.S_CODE}");
                    }
                    else {
                        trans.RollbackTran();
                        return BuildSimpleResult(5, $"生成 产品出库(WMS) 失败,容器号{locCtnrRel.S_CNTR_CODE},起点{startLoc.S_CODE},终点{endLoc.S_CODE}");
                        return BuildSimpleResult(5, $"生成 产品部分出库 失败,容器号{locCtnrRel.S_CNTR_CODE},起点{startLoc.S_CODE},终点{endLoc.S_CODE}");
                    }
                }
            }
@@ -207,13 +221,13 @@
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult PartInWarehouse(PartInWarehouseInfo model) {
        internal static SimpleResult PartInbound(PartInboundInfo model) {
            LogHelper.Info("触发API:产品部分回库(WMS)" + JsonConvert.SerializeObject(model), "API");
            var db = DbHelper.GetDbClient();
            try {
                // 起点位置:取放货区(有货物、没有锁、已启用)
                var startLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 1 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == AreaCode.收发货位区);
                var startLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 1 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == AreaCode.收发区);
                if (startLoc == null) {
                    return BuildSimpleResult(2, $"起点位置 {model.startLoc} 不符合回库条件");
                }
@@ -255,13 +269,13 @@
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult CheckOutWarehouse(CheckOutWarehouseInfo model) {
        internal static SimpleResult CheckOutbound(CheckOutboundInfo model) {
            LogHelper.Info("触发API:盘点理货出库(WMS)" + JsonConvert.SerializeObject(model), "API");
            var db = DbHelper.GetDbClient();
            try {
                // 起点位置:取放货区(有货物、没有锁、已启用)
                var startLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 1 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == AreaCode.收发货位区);
                var startLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 1 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == AreaCode.收发区);
                if (startLoc == null) {
                    return BuildSimpleResult(2, $"起点位置 {model.startLoc} 不符合出库条件");
                }
@@ -303,13 +317,13 @@
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult CheckInWarehouse(CheckInWarehouseInfo model) {
        internal static SimpleResult CheckInbound(CheckInboundInfo model) {
            LogHelper.Info("触发API:盘点理货回库(WMS)" + JsonConvert.SerializeObject(model), "API");
            var db = DbHelper.GetDbClient();
            try {
                // 起点位置:取放货区(有货物、没有锁、已启用)
                var startLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 1 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == AreaCode.收发货位区);
                var startLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 1 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == AreaCode.收发区);
                if (startLoc == null) {
                    return BuildSimpleResult(2, $"起点位置 {model.startLoc} 不符合回库条件");
                }
@@ -344,24 +358,6 @@
            catch (Exception ex) {
                return BuildSimpleResult(1, $"发生了异常:{ex.Message}");
            }
        }
        /// <summary>
        /// 入库数据同步(ERP)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult InWarehouseDataSync(InWarehouseDataSyncInfo model) {
            return BuildSimpleResult(0, "");
        }
        /// <summary>
        /// 出库发料同步(ERP)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult OutWarehouseDataSync(OutWarehouseDataSyncInfo model) {
            return BuildSimpleResult(0, "");
        }
    }
}