using HslCommunication; using MailKit.Search; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Reflection.Metadata; using System.Text; using System.Threading.Tasks; using WIDESEA_Common.StockEnum; using WIDESEA_Common.TaskEnum; using WIDESEA_Common.WareHouseEnum; using WIDESEA_Core; using WIDESEA_Core.BaseRepository; using WIDESEA_Core.BaseServices; using WIDESEA_Core.Enums; using WIDESEA_Core.Helper; using WIDESEA_DTO.SquareCabin; using WIDESEA_ISquareCabinServices; using WIDESEA_IWMsInfoServices; using WIDESEA_Model.Models; using static WIDESEA_DTO.SquareCabin.OrderDto; using static WIDESEA_DTO.SquareCabin.TowcsDto; namespace WIDESEA_SquareCabinServices { public class InventoryServices : ServiceBase>, IInventoryServices { private readonly IDeliveryOrderServices _deliveryOrderServices; public InventoryServices(IRepository BaseDal, IDeliveryOrderServices deliveryOrderServices) : base(BaseDal) { _deliveryOrderServices = deliveryOrderServices; } /// /// 获取上游库存信息 /// /// 商品编码 /// 批号 /// /// public WebResponseContent GetInventoryList(string goods_no, string batch_num) { var responseContent = new WebResponseContent(); try { var url = "http://121.37.118.63/GYZ2/95fck/repositoryInfo"; var result = HttpHelper.Post(url, new { goods_no, batch_num }.ToJsonString()); var response = JsonConvert.DeserializeObject>(result); if (response.resultCode != "0") { SendErrorToUpstream(8, "", response.resultMsg ?? "上游接口返回失败", ""); return responseContent.Error(response.resultMsg ?? "上游接口返回失败"); } if (response.data == null || !response.data.Any()) { return responseContent.OK("无新库存数据"); } Db.Ado.BeginTran(); foreach (var item in response.data) { // 使用 FirstOrDefault 避免找不到记录时抛出异常 var Inver = Db.Queryable() .First(x => x.MaterielCode == item.goods_no && x.BatchNo == item.batch_num); if (Inver != null) { Inver.ERPStockQuantity = item.business_qty; Db.Updateable(Inver).ExecuteCommand(); } } Db.Ado.CommitTran(); return responseContent.OK("库存信息同步完成"); } catch (Exception ex) { Db.Ado.RollbackTran(); SendErrorToUpstream(8, "", ex.Message, ""); return responseContent.Error("同步失败: " + ex.Message); } } /// /// wcs回传给我调用我的方法 不管是入库 出库 盘点都会调用这个接口 /// /// /// public ApiResponse OrderFeedback(EdiOrderCallbackRequest request) { try { // 1️⃣ 校验请求 if (request == null || request.details == null || !request.details.Any()) { return new ApiResponse { code = "500", msg = "请求参数无效" }; } var reslut = WarehouseEnum.立库.ObjToInt().ToString("000"); // 2️⃣ 开启事务 BaseDal.Db.Ado.BeginTran(); foreach (var detail in request.details) { #region 查询物料信息、计算总和 //查询物料表 var goods = Db.Queryable().Where(x => x.MaterielCode == detail.productCode).First(); if (goods == null) throw new Exception($"未找到物料编码【{detail.productCode}】的物料信息"); // 3️ 计算入库数量(取正)遍历 orderDetails 中的每个 EdiOrderBoxDto 对象 decimal orderQty = detail.orderDetails? .Sum(x => decimal.TryParse(x.quantity, out var q) ? Math.Abs(q) : 0) ?? 0; #endregion // 7️⃣ 按订单类型执行不同逻辑 switch (request.orderType) { case "1": //入库 { #region 处理入库订单 Dt_CabinOrder cabinOrder = Db.Queryable().Where(x => x.Order_no == request.externalOrderNo && x.Warehouse_no == reslut).Includes(x => x.Details).First(); if (cabinOrder == null) throw new Exception($"未找到入库单号【{request.externalOrderNo}】的入库单信息"); #region 判断是否为盘盈入库单 if (cabinOrder.Order_type == "5") { foreach (var item in cabinOrder.Details) { Dt_InventoryInfo inventoryInfo = BaseDal.Db.Queryable() .First(x => x.MaterielCode == item.Goods_no && x.BatchNo == item.Batch_num && x.LocationCode == reslut); var qty = inventoryInfo.SupplyQuantity - inventoryInfo.StockQuantity; if (orderQty != qty) throw new Exception($"盘盈入库数量不一致,上传数量【{orderQty}】,库存盘盈数量【{qty}】"); inventoryInfo.StockQuantity = inventoryInfo.SupplyQuantity; inventoryInfo.SupplyQuantity = 0; inventoryInfo.StockStatus = StockStatusEmun.入库完成.ObjToInt(); #region 添加盘盈入库任务 Dt_SupplyTask_Hty supplyTask_Hty = new Dt_SupplyTask_Hty() { WarehouseCode = inventoryInfo.WarehouseCode, OperateType = OperateTypeEnum.自动完成.ToString(), InsertTime = DateTime.Now, TaskStatus = SupplyStatusEnum.InFinish.ObjToInt(), BatchNo = inventoryInfo.BatchNo, MaterielName = inventoryInfo.MaterielName, MaterielCode = inventoryInfo.MaterielCode, MaterielSpec = inventoryInfo.MaterielSpec, TaskType = TaskTypeEnum.ChenckIn.ObjToInt(), CreateDate = DateTime.Now, Creater = App.User.UserName, LocationCode = inventoryInfo.LocationCode, OrderNo = cabinOrder.Order_no, StockQuantity = orderQty, SupplyQuantity = 0, Remark = "盘盈入库" }; #endregion var inventory_Batch = BaseDal.Db.Queryable() .First(x => x.MaterielCode == inventoryInfo.MaterielCode && x.BatchNo == inventoryInfo.BatchNo); inventory_Batch.StockQuantity = inventory_Batch.SupplyQuantity; inventory_Batch.SupplyQuantity = 0; item.OrderDetailStatus = "已完成"; BaseDal.Db.Updateable(item).ExecuteCommand(); BaseDal.Db.Updateable(inventoryInfo).ExecuteCommand(); BaseDal.Db.Updateable(inventory_Batch).ExecuteCommand(); BaseDal.Db.Insertable(supplyTask_Hty).ExecuteCommand(); } var cabinOrder1 = BaseDal.Db.Queryable().Where(x => x.Id == cabinOrder.Id).Includes(x => x.Details).First(); if (!cabinOrder1.Details.Where(x => x.OrderDetailStatus != "已完成").Any()) cabinOrder.OdrderStatus = "已完成"; BaseDal.Db.Updateable(cabinOrder).ExecuteCommand(); } #endregion else { if (cabinOrder == null || cabinOrder.OdrderStatus == "已完成") throw new Exception($"入库单已完成"); Dt_CabinOrderDetail cabinOrderDetail = cabinOrder.Details.Where(x => x.Goods_no == detail.productCode && x.Batch_num == detail.batchNo && x.Status == 1).First(); if (cabinOrderDetail == null || cabinOrderDetail.OrderDetailStatus == "已完成") throw new Exception($"入库单明细已完成"); cabinOrderDetail.Order_Inqty += orderQty; if (cabinOrderDetail.Order_Inqty > cabinOrderDetail.Order_qty) throw new Exception($"入库数量不可超出单据数量"); cabinOrder.OdrderStatus = "开始"; cabinOrderDetail.OrderDetailStatus = "开始"; if (cabinOrderDetail.Order_Inqty == cabinOrderDetail.Order_qty) cabinOrderDetail.OrderDetailStatus = "已完成"; BaseDal.Db.Updateable(cabinOrderDetail).ExecuteCommand(); var cabinOrder1 = BaseDal.Db.Queryable().Where(x => x.Order_no == cabinOrder.Order_no && x.Warehouse_no == reslut).Includes(x => x.Details).First(); if (!cabinOrder1.Details.Where(x => x.OrderDetailStatus != "已完成").Any()) cabinOrder.OdrderStatus = "已完成"; BaseDal.Db.Updateable(cabinOrder).ExecuteCommand(); #endregion #region 创建库存信息 // 5️⃣ 查询库存详情 var inventoryInfo = BaseDal.Db.Queryable() .First(x => x.MaterielCode == cabinOrderDetail.Goods_no && x.BatchNo == cabinOrderDetail.Batch_num && x.LocationCode == "立库"); if (inventoryInfo != null) { inventoryInfo.StockQuantity += orderQty; inventoryInfo.AvailableQuantity += orderQty; inventoryInfo.InDate = DateTime.Now; BaseDal.Db.Updateable(inventoryInfo).ExecuteCommand(); } else { inventoryInfo = new Dt_InventoryInfo { PalletCode = detail.orderDetails?.FirstOrDefault()?.palletCode ?? "", WarehouseCode = "001", LocationCode = "立库", StockStatus = StockStatusEmun.入库完成.ObjToInt(), MaterielCode = goods.MaterielCode, MaterielName = goods.MaterielName, MaterielSpec = goods.MaterielSpec, BatchNo = detail.batchNo, StockQuantity = orderQty, OutboundQuantity = 0, SupplyQuantity = 0, AvailableQuantity = orderQty, InDate = DateTime.Now, ProductionDate = detail.finishDate.ToString("yyyy-MM-dd"), ShelfLife = 0, ValidityPeriod = cabinOrderDetail.Exp_date, Remark = "WCS回传创建" }; BaseDal.Db.Insertable(inventoryInfo).ExecuteCommand(); } #endregion #region 创建库存批次信息 // 6️⃣ 查询库存批次信息 var inventory_Batch = BaseDal.Db.Queryable() .First(x => x.MaterielCode == inventoryInfo.MaterielCode && x.BatchNo == inventoryInfo.BatchNo); if (inventory_Batch != null) { inventory_Batch.StockQuantity += orderQty; inventory_Batch.AvailableQuantity += orderQty; BaseDal.Db.Updateable(inventory_Batch).ExecuteCommand(); } else { inventory_Batch = new Dt_Inventory_Batch { MaterielCode = inventoryInfo.MaterielCode, MaterielName = inventoryInfo.MaterielName, MaterielSpec = inventoryInfo.MaterielSpec, BatchNo = inventoryInfo.BatchNo, StockQuantity = inventoryInfo.StockQuantity, OutboundQuantity = inventoryInfo.OutboundQuantity, AvailableQuantity = inventoryInfo.AvailableQuantity, SupplyQuantity = inventoryInfo.SupplyQuantity, ERPStockQuantity = 0, Status = false, ProductionDate = detail.finishDate.ToString("yyyy-MM-dd"), ValidityPeriod = inventoryInfo.ValidityPeriod.ObjToDate(), Remark = "自动创建" }; BaseDal.Db.Insertable(inventory_Batch).ExecuteCommand(); } #endregion #region 添加入库任务历史 Dt_SupplyTask_Hty supplyTask_Hty = new Dt_SupplyTask_Hty() { WarehouseCode = inventoryInfo.WarehouseCode, TaskNum = cabinOrderDetail.Id, OperateType = OperateTypeEnum.自动完成.ToString(), InsertTime = DateTime.Now, TaskStatus = SupplyStatusEnum.InFinish.ObjToInt(), BatchNo = inventoryInfo.BatchNo, MaterielName = inventoryInfo.MaterielName, MaterielCode = inventoryInfo.MaterielCode, MaterielSpec = inventoryInfo.MaterielSpec, TaskType = cabinOrder.Order_type == "1" ? TaskTypeEnum.In.ObjToInt() : TaskTypeEnum.OutReturn.ObjToInt(), CreateDate = DateTime.Now, Creater = App.User.UserName, LocationCode = inventoryInfo.LocationCode, OrderNo = cabinOrder.Order_no, StockQuantity = orderQty, SupplyQuantity = 0, Remark = "入库" }; BaseDal.Db.Insertable(supplyTask_Hty).ExecuteCommand(); #endregion } } break; case "2": { Dt_DeliveryOrder cabinOrder = Db.Queryable().Where(x => x.Out_no == request.externalOrderNo && x.Warehouse_no == reslut).Includes(x => x.Details).First(); if (cabinOrder == null) throw new Exception($"未找到出库单号【{request.externalOrderNo}】的入库单信息"); if (cabinOrder.Out_type == "6") { foreach (var item in cabinOrder.Details) { Dt_InventoryInfo inventoryInfo = BaseDal.Db.Queryable() .First(x => x.MaterielCode == item.Goods_no && x.BatchNo == item.Batch_num && x.LocationCode == reslut); var qty = inventoryInfo.StockQuantity - inventoryInfo.SupplyQuantity; if (orderQty != qty) throw new Exception($"盘亏出库数量不一致,上传数量【{orderQty}】,库存盘亏数量【{qty}】"); inventoryInfo.StockQuantity = inventoryInfo.SupplyQuantity; inventoryInfo.SupplyQuantity = 0; inventoryInfo.StockStatus = StockStatusEmun.入库完成.ObjToInt(); #region 添加盘亏出库任务 Dt_SupplyTask_Hty supplyTask_Hty = new Dt_SupplyTask_Hty() { WarehouseCode = inventoryInfo.WarehouseCode, OperateType = OperateTypeEnum.自动完成.ToString(), InsertTime = DateTime.Now, TaskStatus = SupplyStatusEnum.OutFinish.ObjToInt(), BatchNo = inventoryInfo.BatchNo, MaterielName = inventoryInfo.MaterielName, MaterielCode = inventoryInfo.MaterielCode, MaterielSpec = inventoryInfo.MaterielSpec, TaskType = TaskTypeEnum.ChenckOut.ObjToInt(), CreateDate = DateTime.Now, Creater = App.User.UserName, LocationCode = inventoryInfo.LocationCode, OrderNo = cabinOrder.Out_no, StockQuantity = orderQty, SupplyQuantity = 0, Remark = "盘亏出库" }; #endregion var inventory_Batch = BaseDal.Db.Queryable() .First(x => x.MaterielCode == inventoryInfo.MaterielCode && x.BatchNo == inventoryInfo.BatchNo); inventory_Batch.StockQuantity = inventory_Batch.SupplyQuantity; inventory_Batch.SupplyQuantity = 0; item.OotDetailStatus = "已完成"; BaseDal.Db.Updateable(item).ExecuteCommand(); BaseDal.Db.Updateable(inventoryInfo).ExecuteCommand(); BaseDal.Db.Updateable(inventory_Batch).ExecuteCommand(); BaseDal.Db.Insertable(supplyTask_Hty).ExecuteCommand(); } var cabinOrder1 = BaseDal.Db.Queryable().Where(x => x.Id == cabinOrder.Id).Includes(x => x.Details).First(); if (!cabinOrder1.Details.Where(x => x.OotDetailStatus != "已完成").Any()) cabinOrder.OutStatus = "已完成"; BaseDal.Db.Updateable(cabinOrder).ExecuteCommand(); } else { #region 找出库任务 Dt_SupplyTask supplyTask = Db.Queryable().Where(x => x.MaterielCode == detail.productCode && x.BatchNo == detail.batchNo && x.OrderNo == request.externalOrderNo && x.WarehouseCode == reslut && x.TaskStatus == SupplyStatusEnum.NewOut.ObjToInt()).First(); if (supplyTask == null) throw new Exception($"未找到订单号【{request.externalOrderNo}】物料编号【{detail.productCode}】的出库任务"); if (supplyTask.StockQuantity != orderQty) throw new Exception($"订单号【{request.orderNo}】物料编号【{detail.productCode}】的出库数量与出库任务数量不相等"); #endregion #region 处理出库单、库存信息、出库任务、调拨任务 var content = _deliveryOrderServices.OutTaskFinish(supplyTask); if (!content.Status) throw new Exception(content.Message); #endregion } } break; case "3": // 盘点 { var WarehouseLK = WarehouseEnum.立库.ObjToInt().ToString("000"); #region 找盘点任务 Dt_SupplyTask supplyTask = Db.Queryable().Where(x => x.MaterielCode == detail.productCode && x.BatchNo == detail.batchNo && x.OrderNo == request.externalOrderNo && x.WarehouseCode == WarehouseLK && x.TaskStatus == SupplyStatusEnum.NewCheck.ObjToInt()).First(); if (supplyTask == null) throw new Exception($"未找到订单号【{request.externalOrderNo}】物料编号【{detail.productCode}】的盘点任务"); #endregion if (detail.isLossOrProfit == 1) // 盘亏 { supplyTask.SupplyQuantity = supplyTask.StockQuantity - detail.ea; } else if (detail.isLossOrProfit == 2) // 盘盈 { supplyTask.SupplyQuantity = supplyTask.StockQuantity + detail.ea; } else // 盘中 { supplyTask.SupplyQuantity = supplyTask.StockQuantity; } var content = _deliveryOrderServices.CheckTaskFinish(supplyTask); if (!content.Status) throw new Exception(content.Message); } break; } } // 9️⃣ 提交事务 BaseDal.Db.Ado.CommitTran(); return new ApiResponse { code = "0", msg = "成功" }; } catch (Exception ex) { // 🔟 回滚事务 BaseDal.Db.Ado.RollbackTran(); return new ApiResponse { code = "500", msg = $"处理失败: {ex.Message}" }; } } /// /// 更新入库单详细 /// /// 批次号 /// 物料名编码/param> public void UpdateInboundOrderDetailStatus(string orderNo, string batchNo, string productCode) { try { //查询详情 var detail = BaseDal.Db.Queryable() .First(x => x.Goods_no == productCode && x.Batch_num == batchNo && x.OrderDetailStatus == "开始" && x.Status == 1); //查找到后根据物料状态(OrderDetailStatus==开始) 该状态Status=1修改该条详情的OrderDetailStatus==已完成 detail.OrderDetailStatus = "已完成"; BaseDal.Db.Updateable(detail).ExecuteCommand(); } catch (Exception ex) { throw; } } /// /// //查找到后根据物料状态(OrderDetailStatus==开始) 该状态Status=1修改该条详情的OrderDetailStatus==已完成 /// /// /// public void UpdateOutboundOrderDetailStatus(string batchNo, string productCode) { try { //查询详情 var detail = BaseDal.Db.Queryable() .First(x => x.Goods_no == productCode && x.Batch_num == batchNo && x.OotDetailStatus == "开始" && x.Status == 1); detail.OotDetailStatus = "已完成"; BaseDal.Db.Updateable(detail).ExecuteCommand(); } catch (Exception ex) { throw; } } /// /// 推送异常信息给上游系统1.入库单接口;2.入库单报完成接口;3.出库单接口;4.出库报完成接口;5.药品基础信息同步接口;6.供应商信息接口;7.客户信息接口;8.库存 /// public void SendErrorToUpstream(int type, string code, string message, string remark) { try { var url = "http://121.37.118.63:80/GYZ2/95fck/exceptionLog"; var requestData = new { type = type.ToString(), code = code, message = message, remark = remark }; var result = HttpHelper.Post(url, requestData.ToJsonString()); // 可以反序列化检查 resultCode 是否为0 } catch (Exception e) { // 这里不要再抛异常了,避免死循环 Console.WriteLine("异常接口推送失败:" + e.Message); } } } }