using HslCommunication; using Newtonsoft.Json; using SqlSugar; using WIDESEA_Common; using WIDESEA_Common.OrderEnum; 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 ICabinOrderServices _cabinOrderServices; private readonly IDeliveryOrderServices _deliveryOrderServices; private readonly ISupplyTaskService _supplyTaskService; private readonly IInventory_BatchServices _inventoryBatchServices; private readonly IMessageInfoService _infoService; public InventoryServices(IRepository BaseDal, ICabinOrderServices cabinOrderServices, IDeliveryOrderServices deliveryOrderServices, ISupplyTaskService supplyTaskService, IInventory_BatchServices inventoryBatchServices, IMessageInfoService infoService) : base(BaseDal) { _cabinOrderServices = cabinOrderServices; _deliveryOrderServices = deliveryOrderServices; _supplyTaskService = supplyTaskService; _inventoryBatchServices = inventoryBatchServices; _infoService = infoService; } /// /// 获取上游库存信息 /// /// 商品编码 /// 批号 /// /// public WebResponseContent GetInventoryList(int[] keys) { var responseContent = new WebResponseContent(); try { //根据id查询库存批次信息表,获取到他们的商品编码和批次号 var inventoryBatches = _inventoryBatchServices.Repository.QueryData(x => keys.Contains(x.Id)); //查全部 var url = "http://121.37.118.63:80/GYZ2/95fck/repositoryInfo"; foreach (var item in inventoryBatches) { var result = HttpHelper.Post(url, new { goods_no = item.MaterielCode, batch_num = item.BatchNo }.ToJsonString()); var response = JsonConvert.DeserializeObject>(result); if (response == null) continue; var data = response.data.FirstOrDefault(); if (data != null) item.ERPStockQuantity = data.business_qty; } _inventoryBatchServices.UpdateData(inventoryBatches); return responseContent.OK("库存信息同步完成"); } catch (Exception ex) { return responseContent.Error("同步失败: " + ex.Message); } } /// /// 不论是出库入库盘点,wcs都会调用我这个方法 /// /// /// public ApiResponse OrderFeedback(EdiOrderCallbackRequest request) { try { if (request == null || request.details == null || request.details.Count < 1) throw new Exception("请求参数无效"); var Warecode = WarehouseEnum.立库.ObjToInt().ToString("000"); switch (request.orderType) { case "1": //入库 { Dt_CabinOrder cabinOrder = _cabinOrderServices.Db.Queryable().Where(x => x.Order_no == request.externalOrderNo && x.Warehouse_no == Warecode).Includes(x => x.Details).First(); if (cabinOrder == null) throw new Exception($"未找到入库单号【{request.externalOrderNo}】的入库单信息"); if (cabinOrder.OdrderStatus == "已完成") return new ApiResponse { code = "0", msg = $"成功" }; WebResponseContent content = _cabinOrderServices.CompleteLKInOrder(cabinOrder, request); if (!content.Status) throw new Exception(content.Message); } break; case "2": { Dt_DeliveryOrder deliveryOrder = _deliveryOrderServices.Db.Queryable().Where(x => x.Out_no == request.externalOrderNo && x.Warehouse_no == Warecode).Includes(x => x.Details).First(); if (deliveryOrder == null) throw new Exception($"未找到出库单号【{request.externalOrderNo}】的出库单信息"); if (deliveryOrder.OutStatus == "已完成") return new ApiResponse { code = "0", msg = $"成功" }; WebResponseContent content = _deliveryOrderServices.CompleteLKOutOrder(deliveryOrder, request); if (!content.Status) throw new Exception(content.Message); } break; case "3": { #region 找盘点任务 List supplyTasks = _supplyTaskService.Repository.QueryData(x => x.OrderNo == request.externalOrderNo && x.WarehouseCode == Warecode && x.TaskStatus == SupplyStatusEnum.NewCheck.ObjToInt()); foreach (var detail in request.details) { Dt_SupplyTask? supplyTask = supplyTasks.Where(x => x.MaterielCode == detail.productCode && x.BatchNo == detail.batchNo).FirstOrDefault(); if (supplyTask == null) throw new Exception($"未找到订单号【{request.externalOrderNo}】物料编号【{detail.productCode}】的盘点任务"); 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); } #endregion } break; default: throw new Exception($"未定义的类型【{request.orderType}】"); } return new ApiResponse { code = "0", msg = $"成功" }; } catch (Exception ex) { return new ApiResponse { code = "500", msg = $"处理失败: {ex.Message}" }; } } /// /// wcs回传给我调用我的方法 不管是入库 出库 盘点都会调用这个接口 /// /// /// public ApiResponse OrderFeedback1(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.OdrderStatus == "已完成") return new ApiResponse { code = "0", msg = "成功" }; 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 = "智能立库" }; BaseDal.Db.Insertable(inventoryInfo).ExecuteCommand(); } #endregion #region 创建库存批次信息 只有不是调拨入库单(115)才对批次信息进行修改 if (cabinOrder.Order_type != InOrderTypeEnum.Allocat.ObjToInt().ToString()) { // 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 = "入库" }; //这里这里的入库调拨单状态是115,就将调拨任务状态改为7 if (cabinOrder.Order_type == InOrderTypeEnum.Allocat.ObjToInt().ToString()) supplyTask_Hty.TaskType = TaskTypeEnum.AllocatIn.ObjToInt(); 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}" }; //Console.WriteLine(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); } } } }