kazelee
2025-06-09 fe3167683576e5dd943fd5acc52e713652365def
优化ERP下发库存/取货信息流程,添加记录表和header判断逻辑备用
2 文件已重命名
1个文件已添加
3个文件已修改
3个文件已删除
280 ■■■■■ 已修改文件
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/7edb35ec-db87-44fb-92d8-217fedcfbfc4.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/8d71ff97-9b72-48d6-9f47-39b04040aec2.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/99373dd3-bbba-4020-a01f-9c6df7555363.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/cebd90f0-0f2c-46b9-a251-1039546e19c0.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3.AnGang.csproj 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/ApiHelper.cs 92 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/ErpController.cs 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
models/TN_Inbound_DataRecord.cs 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
models/TN_Outbound_DataRecord.cs 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/7edb35ec-db87-44fb-92d8-217fedcfbfc4.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/8d71ff97-9b72-48d6-9f47-39b04040aec2.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/99373dd3-bbba-4020-a01f-9c6df7555363.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/cebd90f0-0f2c-46b9-a251-1039546e19c0.vsidx
Binary files differ
HH.WCS.Mobox3.AnGang.csproj
@@ -270,8 +270,8 @@
    <Compile Include="models\TN_Count_Diff.cs" />
    <Compile Include="models\TN_Count_Order.cs" />
    <Compile Include="models\TN_Count_Plan.cs" />
    <Compile Include="models\TN_Inbound_Order.cs" />
    <Compile Include="models\TN_Outbound_Order.cs" />
    <Compile Include="models\TN_Inbound_DataRecord.cs" />
    <Compile Include="models\TN_Outbound_DataRecord.cs" />
    <Compile Include="core\WMSCore.cs" />
    <Compile Include="models\BaseModel.cs" />
    <Compile Include="device\ModbusHelper.cs" />
api/ApiHelper.cs
@@ -686,34 +686,67 @@
        }
        public static ErpResult InboundDataSync(InboundDataSyncInfo model) {
            //return BuildErpResult(1, "测试");
            var db = new SqlHelper<object>().GetInstance();
            try {
                var err = "";
                var cgDetailList = new List<TN_CG_Detail>();
                foreach (var inboundData in model.stockTransactions) {
                var recordList = new List<TN_Inbound_DataRecord>();
                foreach (var transaction in model.stockTransactions) {
                    // 写入记录表
                    var record = new TN_Inbound_DataRecord {
                        S_LOCATION_CODE = transaction.locationCode,
                        S_STOCK_TRANS = transaction.stockTransactionId,
                        S_ITEM_CODE = transaction.itemCode,
                        S_ITEM_NAME = transaction.itemName,
                        S_ITEM_SHORT_DESC = transaction.itemShortDesc,
                        S_STOCK_QUANTITY = transaction.stockQuantity,
                        S_IN_QUANTITY = transaction.inQuantity,
                        S_TOTAL_PRICE = transaction.totalPrice,
                        S_STOCK_IN_TIME = transaction.stockInTime,
                        S_STORE_KEEPER = transaction.storeKeeper,
                        S_LINE_CODE = transaction.lineCode,
                        S_DELIVERY_ITEM_NO = transaction.deliveryItemNo,
                        S_SUPPLIER_NAME = transaction.supplierName,
                        S_INVENTORY_MAN = transaction.inventoryManager
                    };
                    recordList.Add(record);
                    // 查询对应物料
                    var cgDetail = 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 => l.S_CODE == inboundData.locationCode)
                        .Where(l => l.S_CODE == transaction.locationCode)
                        .Select((l, c, d) => d)
                        .First();
                    
                    if (cgDetail == null) {
                        err += $"储位码{inboundData.locationCode}对应的货位物料不存在!";
                        err += $"储位码{transaction.locationCode}对应的货位物料不存在!";
                        continue;
                    }
                    cgDetail.S_ITEM_CODE = inboundData.itemCode;
                    cgDetail.S_ITEM_NAME = inboundData.itemName;
                    cgDetail.S_ITEM_CODE = transaction.itemCode;
                    cgDetail.S_ITEM_NAME = transaction.itemName;
                    
                    cgDetailList.Add(cgDetail);
                }
                
                using (var tran = db.Ado.UseTran()) {
                    if (db.Insertable<TN_Inbound_DataRecord>(recordList).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return BuildErpResult(500, $"写入入库记录表失败");
                    }
                if (db.Updateable<TN_CG_Detail>(cgDetailList).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                    return BuildErpResult(500, $"更改物料信息失败");
                }
                    tran.CommitTran();
                }
                if (err != "") {
                    return BuildErpResult(2, err);
                    return BuildErpResult(2, err + "其他信息正常已写入");
                }
                return BuildErpResult(0, $"更改物料信息成功");
@@ -724,34 +757,67 @@
        }
        public static ErpResult OutboundDataSync(OutboundDataSyncInfo model) {
            //return BuildErpResult(1, "测试");
            var db = new SqlHelper<object>().GetInstance();
            try {
                var err = "";
                var cgDetailList = new List<TN_CG_Detail>();
                foreach (var inboundData in model.materialIssues) {
                var recordList = new List<TN_Outbound_DataRecord>();
                foreach (var issue in model.materialIssues) {
                    // 写入记录表
                    var record = new TN_Outbound_DataRecord {
                        S_LOCATION_CODE = issue.locationCode,
                        S_ORDER_NO = issue.withdrawalOrderNo,
                        S_ITEM_CODE = issue.itemCode,
                        S_ITEM_NAME = issue.itemName,
                        S_SHORT_DESC = issue.itemShortDesc,
                        S_ACTUAL_QTY = issue.actualIssuedQty,
                        S_ISSUED_AMOUNT = issue.issuedAmount,
                        S_SUPPLIER_NAME = issue.supplierName,
                        S_ISSUER = issue.issuer,
                        S_ISSUE_DATE = issue.issueDate,
                        S_STORE_KEEPER = issue.storeKeeper,
                        S_LINE_CODE = issue.lineCode,
                        S_BATCH_NO = issue.batchNo
                    };
                    recordList.Add(record);
                    // 查询对应物料
                    var cgDetail = 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 => l.S_CODE == inboundData.locationCode)
                        .Where(l => l.S_CODE == issue.locationCode)
                        .Select((l, c, d) => d)
                        .First();
                    if (cgDetail == null) {
                        err += $"储位码{inboundData.locationCode}对应的货位物料不存在!";
                        err += $"储位码{issue.locationCode}对应的货位物料不存在!";
                        continue;
                    }
                    cgDetail.S_ITEM_CODE = inboundData.itemCode;
                    cgDetail.S_ITEM_NAME = inboundData.itemName;
                    cgDetail.S_ITEM_CODE = issue.itemCode;
                    cgDetail.S_ITEM_NAME = issue.itemName;
                    cgDetailList.Add(cgDetail);
                }
                using (var tran = db.Ado.UseTran()) {
                    if (db.Insertable<TN_Outbound_DataRecord>(recordList).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return BuildErpResult(500, $"写入出库记录表失败");
                    }
                if (db.Updateable<TN_CG_Detail>(cgDetailList).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                    return BuildErpResult(500, $"更改物料信息失败");
                }
                    tran.CommitTran();
                }
                if (err != "") {
                    return BuildErpResult(2, err);
                    return BuildErpResult(2, err + "其他信息正常已写入");
                }
                return BuildErpResult(0, $"更改物料信息成功");
api/ErpController.cs
@@ -1,6 +1,13 @@
using System.Web.Http;
using System.Linq;
using System.Net.Http;
using System.Net;
using System.Text;
using System.Web.Http;
using Newtonsoft.Json;
using static HH.WCS.Mobox3.AnGang.api.OtherModel;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.api {
    /// <summary>
@@ -15,8 +22,19 @@
        /// <returns></returns>
        [HttpPost]
        [Route("InboundDataSync")]
        public ErpResult InboundDataSync(InboundDataSyncInfo model) {
            return ApiHelper.InboundDataSync(model);
        public IHttpActionResult InboundDataSync(InboundDataSyncInfo model) {
            LogHelper.Info("触发API:入库数据同步" + JsonConvert.SerializeObject(model), "API");
            //var headers = Request.Headers; // 暂不考虑对请求HTTP进行校验,默认发来的请求格式都正确
            //return new ErpResult { errCode = 1, errMsg = "测试" };
            //return CreateSuccessResponse(new ErpResult { errCode = 1, errMsg = "测试"});
            //var headers = Request.Headers;
            //return ProcessInboundData(headers, model);
            //return ApiHelper.InboundDataSync(model);
            return NormalProcessInboundData(model); // 暂时使用原本的逻辑
        }
        /// <summary>
@@ -26,8 +44,147 @@
        /// <returns></returns>
        [HttpPost]
        [Route("OutboundDataSync")]
        public ErpResult OutboundDataSync(OutboundDataSyncInfo model) {
            return ApiHelper.OutboundDataSync(model);
        public IHttpActionResult OutboundDataSync(OutboundDataSyncInfo model) {
            LogHelper.Info("触发API:出库发料同步" + JsonConvert.SerializeObject(model), "API");
            //var headers = Request.Headers;
            //return ProcessOutboundData(headers, model);
            //return ApiHelper.OutboundDataSync(model);
            return NormalProcessOutboundData(model); // 暂时使用原本的逻辑
        }
        private IHttpActionResult NormalProcessInboundData(InboundDataSyncInfo model) {
            var data = ApiHelper.InboundDataSync(model);
            return ResponseMessage(new HttpResponseMessage(HttpStatusCode.OK) {
                Headers = { },
                Content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json")
            });
        }
        private IHttpActionResult NormalProcessOutboundData(OutboundDataSyncInfo model) {
            var data = ApiHelper.OutboundDataSync(model);
            return ResponseMessage(new HttpResponseMessage(HttpStatusCode.OK) {
                Headers = { },
                Content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json")
            });
        }
        private IHttpActionResult ProcessInboundData(System.Net.Http.Headers.HttpRequestHeaders headers, InboundDataSyncInfo model) {
            // 必须字段验证
            if (!headers.Contains("sourceAppCode") || !headers.Contains("serviceId") || !headers.Contains("msgSendTime")) {
                return CreateErrorResponse("2003", "缺少必要请求头参数");
            }
            var headerModel = new {
                SourceAppCode = headers.GetValues("sourceAppCode").First(),
                Password = headers.Contains("password") ? headers.GetValues("password").First() : null,
                ServiceId = headers.GetValues("serviceId").First(),
                MsgToken = headers.Contains("msgToken") ? headers.GetValues("msgToken").First() : null,
                MsgSendTime = headers.GetValues("msgSendTime").First()
            };
            // 2. 验证Header
            var validationResult = ValidateHeaders(headerModel);
            if (validationResult != null) {
                return validationResult;
            }
            // 3. 读取Body
            //string requestBody = await Request.Content.ReadAsStringAsync(); // 不需要异步读取,直接用model
            // 4. 验证Body
            if (Request.Content.Headers.ContentLength > 2 * 1024 * 1024) {
                return CreateErrorResponse("2102", "消息内容过长,超过2M");
            }
            // 5. 处理业务逻辑
            var result = ApiHelper.InboundDataSync(model);
            // 6. 返回成功响应
            return CreateSuccessResponse(result);
        }
        private IHttpActionResult ProcessOutboundData(System.Net.Http.Headers.HttpRequestHeaders headers, OutboundDataSyncInfo model) {
            // 必须字段验证
            if (!headers.Contains("sourceAppCode") || !headers.Contains("serviceId") || !headers.Contains("msgSendTime")) {
                return CreateErrorResponse("2003", "缺少必要请求头参数");
            }
            var headerModel = new {
                SourceAppCode = headers.GetValues("sourceAppCode").First(),
                Password = headers.Contains("password") ? headers.GetValues("password").First() : null,
                ServiceId = headers.GetValues("serviceId").First(),
                MsgToken = headers.Contains("msgToken") ? headers.GetValues("msgToken").First() : null,
                MsgSendTime = headers.GetValues("msgSendTime").First()
            };
            // 2. 验证Header
            var validationResult = ValidateHeaders(headerModel);
            if (validationResult != null) {
                return validationResult;
            }
            // 3. 读取Body
            //string requestBody = await Request.Content.ReadAsStringAsync();
            // 4. 验证Body
            if (Request.Content.Headers.ContentLength > 2 * 1024 * 1024) {
                return CreateErrorResponse("2102", "消息内容过长,超过2M");
            }
            // 5. 处理业务逻辑
            var result = ApiHelper.OutboundDataSync(model);
            // 6. 返回成功响应
            return CreateSuccessResponse(result);
        }
        private IHttpActionResult CreateSuccessResponse(object data) {
            return ResponseMessage(new HttpResponseMessage(HttpStatusCode.OK) {
                Headers = { { "returnCode", "0" } },
                Content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json")
            });
        }
        private IHttpActionResult CreateErrorResponse(string code, string message) {
            return ResponseMessage(new HttpResponseMessage(HttpStatusCode.OK) {
                Headers = { { "returnCode", code } },
                Content = new StringContent(message)
            });
        }
        private IHttpActionResult ValidateHeaders(dynamic headers) {
            // 实现所有Header验证逻辑
            if (!IsRegisteredApp(headers.SourceAppCode, headers.Password)) {
                return CreateErrorResponse("2201", "源调用系统未注册");
            }
            if (!IsValidService(headers.ServiceId)) {
                return CreateErrorResponse("2202", "代理服务未注册");
            }
            if (!IsValidDateTime(headers.MsgSendTime)) {
                return CreateErrorResponse("2101", "时间格式校验失败");
            }
            if (!string.IsNullOrEmpty(headers.MsgToken) && headers.MsgToken.Length > 32) {
                return CreateErrorResponse("2104", "消息令牌过长,超过32位");
            }
            return null;
        }
        private bool IsRegisteredApp(string appId, string password) {
            return true;
        }
        private bool IsValidService(string serviceId) {
            return true;
        }
        private bool IsValidDateTime(string dataTime) {
            return true;
        }
    }
}
models/TN_Inbound_DataRecord.cs
File was renamed from models/TN_Inbound_Order.cs
@@ -4,8 +4,11 @@
using System.Text;
using System.Threading.Tasks;
using SqlSugar;
namespace HH.WCS.Mobox3.AnGang.models {
    public class TN_Inbound_Order : BaseModel {
    [SugarTable("TN_Inbound_DataRecord")]
    public class TN_Inbound_DataRecord : BaseModel {
        /// <summary>
        /// 储位码
        /// </summary>
@@ -14,7 +17,7 @@
        /// <summary>
        /// 库存明细交易号
        /// </summary>
        public string S_STOCK_TRANSACTION_ID { get; set; }
        public string S_STOCK_TRANS { get; set; }
        /// <summary>
        /// 物料编码
@@ -74,6 +77,6 @@
        /// <summary>
        /// 库存责任人姓名
        /// </summary>
        public string S_INVENTORY_MANAGER { get; set; }
        public string S_INVENTORY_MAN { get; set; }
    }
}
models/TN_Outbound_DataRecord.cs
File was renamed from models/TN_Outbound_Order.cs
@@ -5,7 +5,7 @@
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.models {
    public class TN_Outbound_Order : BaseModel {
    public class TN_Outbound_DataRecord : BaseModel {
        /// <summary>
        /// 储位码
        /// </summary>
@@ -14,7 +14,7 @@
        /// <summary>
        /// 领用单号
        /// </summary>
        public string S_WITHDRAWAL_ORDER_NO { get; set; }
        public string S_ORDER_NO { get; set; }
        /// <summary>
        /// 物料编码
@@ -29,12 +29,12 @@
        /// <summary>
        /// 物料短描述
        /// </summary>
        public string S_ITEM_SHORT_DESC { get; set; }
        public string S_SHORT_DESC { get; set; }
        /// <summary>
        /// 实发数量
        /// </summary>
        public string S_ACTUAL_ISSUED_QTY { get; set; }
        public string S_ACTUAL_QTY { get; set; }
        /// <summary>
        /// 实发金额