using HslCommunication; using MailKit.Search; using Microsoft.Data.SqlClient; using Microsoft.IdentityModel.Tokens; using Newtonsoft.Json; using OfficeOpenXml.Style; using Org.BouncyCastle.Asn1.X509; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using WIDESEA_Common; using WIDESEA_Common.LocationEnum; using WIDESEA_Common.OrderEnum; 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_IBasicService; using WIDESEA_ISquareCabinServices; using WIDESEA_IWMsInfoServices; using WIDESEA_Model.Models; using static WIDESEA_DTO.SquareCabin.OrderDto; namespace WIDESEA_SquareCabinServices { public partial class DeliveryOrderServices : ServiceBase>, IDeliveryOrderServices { static string SearchDate = ""; private readonly IBasicService _basicService; private readonly IUnitOfWorkManage _unitOfWorkManage; private readonly IInventory_BatchServices _inventory_BatchServices; private readonly IInventoryInfoService _inventoryInfoService; private readonly IDeliveryOrderDetailServices _deliveryOrderDetailServices; private readonly ISupplyTaskService _supplyTaskService; private readonly ICabinOrderServices _cabinOrderServices; public IRepository Repository => BaseDal; public DeliveryOrderServices(IRepository BaseDal, IBasicService basicService, IUnitOfWorkManage unitOfWorkManage, IInventory_BatchServices inventory_BatchServices, IInventoryInfoService inventoryInfoService, IDeliveryOrderDetailServices deliveryOrderDetailServices, ISupplyTaskService supplyTaskService, ICabinOrderServices cabinOrderServices) : base(BaseDal) { _basicService = basicService; _unitOfWorkManage = unitOfWorkManage; _deliveryOrderDetailServices = deliveryOrderDetailServices; _supplyTaskService = supplyTaskService; _inventory_BatchServices = inventory_BatchServices; _inventoryInfoService = inventoryInfoService; _cabinOrderServices = cabinOrderServices; } public WebResponseContent GetUpstreamOutOrder() { var responseContent = new WebResponseContent(); try { var url = "http://121.37.118.63:80/GYZ2/95fck/outOrder"; //var url = "http://127.0.0.1:4523/m1/5660322-5340849-default/GYZ2/95fck/outOrder"; if (string.IsNullOrEmpty(SearchDate)) SearchDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); //// 请求参数 var requestData = new { searchDate = SearchDate //searchDate = "2022-10-10 20:45:16" // 正确的格式 }; SearchDate = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd HH:mm:ss"); var result = HttpHelper.Post(url, requestData.ToJsonString()); var response = JsonConvert.DeserializeObject>(result); if (response.resultCode != "0") { SendErrorToUpstream(3, "", response.resultMsg ?? "上游接口返回失败", ""); return responseContent.Error(response.resultMsg ?? "上游接口返回失败"); } if (response.data == null || !response.data.Any()) { return responseContent.OK("无新出库单数据"); } // 已存在出库单号 var existingOutOrderNos = BaseDal.Db.Queryable() .Select(x => x.Out_no) .ToList(); // 新出库单 var newOutOrders = response.data .Where(outorder => !existingOutOrderNos.Contains(outorder.order_no)) .ToList(); List order_no = newOutOrders.Select(x => x.order_no).ToList(); if (!newOutOrders.Any()) { return responseContent.OK("所有出库单已存在,无需新增"); } Db.Ado.BeginTran(); try { List _DeliveryOrders = new List(); List orderNos = new List(); foreach (var outorder in newOutOrders) { bool skipOrder = false; // 标记是否跳过该出库单 // 如果这个出库单类型不等于1,属于出库退货(要入货上游传过来的数量为负数) if (outorder.order_type != "1") { // 创建出库退货单 - 这里需要根据业务逻辑实现 // 暂时跳过或实现退货逻辑 continue; } else if (outorder.order_type == "1") // 正常出库单 { CreateOutboundOrder(outorder);//创建出库单、处理库存、添加出库任务 // 排除特殊药品,特殊药品直接插入 if (outorder.warehouse_no != "001" && (outorder.warehouse_no == "010" || outorder.warehouse_no == "003" || outorder.warehouse_no == "017")) { var entityOrder = new Dt_DeliveryOrder { Out_no = outorder.order_no, Out_type = outorder.order_type, Client_no = outorder.client_no, Client_name = outorder.client_name, Account_time = outorder.account_time, Warehouse_no = outorder.warehouse_no, OutStatus = "新建", Details = outorder.details.Select(d => new Dt_DeliveryOrderDetail { Goods_no = d.goods_no, Order_qty = Math.Abs(d.order_qty), // 出库数量转为正数 Batch_num = d.batch_num, Exp_date = d.exp_date, OotDetailStatus = "新建", Status = 2, // pad平库,无需同步 }).ToList() }; _DeliveryOrders.Add(entityOrder); } else // 常规药品001房给立库,要是有整箱就给平库 { var entityOrder = new Dt_DeliveryOrder { Out_no = outorder.order_no, Out_type = outorder.order_type, Client_no = outorder.client_no, Client_name = outorder.client_name, Account_time = outorder.account_time, Warehouse_no = outorder.warehouse_no, OutStatus = "新建", Details = new List() }; // 遍历出库明细 foreach (var item in outorder.details) { // 将上游出库数量转为正数 decimal orderQty = Math.Abs((decimal)item.order_qty); #region 根据物料编码查询物料信息 var medication = BaseDal.Db.Queryable() .Where(m => m.MaterielCode == item.goods_no) .First(); // 如果物料信息不存在,跳过整个出库单 if (medication == null) { skipOrder = true; Console.WriteLine($"跳出处库单 {outorder.order_no},原因:未找到商品 [{item.goods_no}] 的物料信息。"); break; } // 若物料不存在或 MaterielSourceType 为空,则跳过整个出库单 if (medication == null || !Enum.IsDefined(typeof(MaterielSourceTypeEnum), medication.MaterielSourceType)) { skipOrder = true; break; } #endregion /// 根据物料信息大小件属性区分是否从立库出库 // 大件从平库出库 if (medication.MaterielSourceType == MaterielSourceTypeEnum.PurchasePart) // 如果物料是大件 { var orderDetail = new Dt_DeliveryOrderDetail() { Reservoirarea = outorder.warehouse_no, Goods_no = item.goods_no, Order_qty = orderQty, Batch_num = item.batch_num, Exp_date = item.exp_date, OotDetailStatus = "新建", Status = 2 // 平库,无需同步 }; entityOrder.Details.Add(orderDetail); } else { Dt_DeliveryOrderDetail orderDetail = null; // 计算整箱和散件数量 var ys = orderQty % medication.BoxQty; // 不能整除箱规的散件数 var xs = (int)(orderQty / medication.BoxQty); // 整箱数量(保留整数) #region 从立库出库散件 #region 判断是否有散件 if (ys > 0 && medication.Business_qty >= ys) { orderDetail = new Dt_DeliveryOrderDetail() { Reservoirarea = outorder.warehouse_no, Goods_no = item.goods_no, Order_qty = ys, Batch_num = item.batch_num, Exp_date = item.exp_date, OotDetailStatus = "新建", Status = 0 // 立库,需要同步给WCS }; medication.Business_qty -= ys; } #endregion #region 判断立库库存是否足够出整箱 while (medication.Business_qty >= medication.BoxQty && xs > 0) { xs--; if (orderDetail == null) { orderDetail = new Dt_DeliveryOrderDetail() { Reservoirarea = outorder.warehouse_no, Goods_no = item.goods_no, Order_qty = medication.BoxQty, Batch_num = item.batch_num, Exp_date = item.exp_date, OotDetailStatus = "新建", Status = 0 // 立库 }; medication.Business_qty -= medication.BoxQty; } else { orderDetail.Order_qty += medication.BoxQty; medication.Business_qty -= medication.BoxQty; } } if (orderDetail != null) entityOrder.Details.Add(orderDetail); #endregion #endregion #region 剩余整件从平库出库 if (xs > 0) { orderDetail = new Dt_DeliveryOrderDetail() { Reservoirarea = outorder.warehouse_no, Goods_no = item.goods_no, Order_qty = medication.BoxQty * xs, Batch_num = item.batch_num, Exp_date = item.exp_date, OotDetailStatus = "新建", Status = 2 // 平库 }; entityOrder.Details.Add(orderDetail); } #endregion } // 更新物料信息 _basicService.MaterielInfoService.Repository.UpdateData(medication); } // 如果跳过该单,则直接continue,不保存 if (skipOrder) { Console.WriteLine($"跳出处库单 {outorder.order_no},因为存在未定义物料属性的商品。"); continue; } // 确保出库单有明细才添加 if (entityOrder.Details.Any()) { _DeliveryOrders.Add(entityOrder); orderNos.Add(outorder.order_no); } } } } // 批量插入出库单和明细 if (_DeliveryOrders.Any()) { BaseDal.Db.InsertNav(_DeliveryOrders).Include(x => x.Details).ExecuteCommand(); } //下发出库单任务给wcs Db.Ado.CommitTran(); var tex = CreateSupplyTask(order_no); if (!tex) { return responseContent.Error("创建供应任务失败"); } return responseContent.OK($"同步出库单成功,共{_DeliveryOrders.Count}条"); } catch (Exception ex) { Db.Ado.RollbackTran(); SendErrorToUpstream(3, "", ex.Message, ""); return responseContent.Error("同步失败: " + ex.Message); } } catch (Exception ex) { SendErrorToUpstream(3, "", ex.Message, ""); return responseContent.Error("同步失败: " + ex.Message); } } /// /// 创建出库单 /// /// /// public WebResponseContent CreateOutboundOrder(UpstramOutOrderInfo outorder) { WebResponseContent webResponseContent = new WebResponseContent(); try { if (outorder.warehouse_no == WarehouseEnum.麻精库.ObjToInt().ToString("000") || outorder.warehouse_no == WarehouseEnum.冷冻库.ObjToInt().ToString("000")) { #region 添加出库单 var entityOrder = new Dt_DeliveryOrder { Out_no = outorder.order_no, Out_type = outorder.order_type, Client_no = outorder.client_no, Client_name = outorder.client_name, Account_time = outorder.account_time, Warehouse_no = outorder.warehouse_no, OutStatus = "新建", Details = outorder.details.Select(d => new Dt_DeliveryOrderDetail { Goods_no = d.goods_no, Order_qty = Math.Abs(d.order_qty), // 出库数量转为正数 Batch_num = d.batch_num, Exp_date = d.exp_date, OotDetailStatus = "新建", Status = 2, // pad平库,无需同步 }).ToList() }; BaseDal.Db.InsertNav(entityOrder).Include(x => x.Details).ExecuteCommand(); #endregion #region 处理库存 #endregion #region 添加出库任务 #endregion } else { } } catch (Exception ex) { webResponseContent.Error(ex.Message); } return webResponseContent; } /// /// 生成出库单任务 /// /// 出库单号 /// private bool CreateSupplyTask(List order_no) { try { // 先获取符合条件的主表数据 var mainOrders = BaseDal.Db.Queryable() .Where(x => order_no.Contains(x.Out_no)) .ToList(); // 获取所有主表ID var mainOrderIds = mainOrders.Select(x => x.Id).ToList(); // 直接查询子表数据 List filteredDetails = BaseDal.Db.Queryable() .Where(d => mainOrderIds.Contains(d.DeliveryOrderId) && d.OotDetailStatus == "新建") .ToList(); // 获取所有需要查询的物料编码 var materielCodes = filteredDetails.Select(x => x.Goods_no).Distinct().ToList(); // 批量查询物料信息 var materielList = BaseDal.Db.Queryable() .Where(x => materielCodes.Contains(x.MaterielCode)) .ToList(); List supplyTasks = new List(); foreach (var item in filteredDetails) { // 根据子表物料编码查询物料信息 var medication = materielList.FirstOrDefault(x => x.MaterielCode == item.Goods_no); // 查找对应的主表信息 var mainOrder = mainOrders.FirstOrDefault(x => x.Id == item.DeliveryOrderId); //随机生成任务编号加时间戳 if (mainOrder == null) continue; var location = Db.Queryable() .Where(x => x.MaterielCode == ""//materielCode && x.BatchNo == ""//batchNo && x.StockQuantity > 0) .OrderBy(x => x.InDate) // 按入库时间排序 .First(); var supplyTask = new Dt_SupplyTask { TaskNum = GenerateTaskNumber(), PalletCode = "0", BatchNo = item.Batch_num, MaterielCode = item.Goods_no, MaterielName = medication?.MaterielName, // 如果物料信息不存在,使用子表的物料名称 MaterielSpec = medication?.MaterielSpec, // 如果物料信息不存在,使用子表的物料规格 TaskType = 0, TaskStatus = item.Status == 0 ? 0 : 1, WarehouseCode = mainOrder.Warehouse_no, LocationCode = item.Status == 0 ? "立库" : "平库", StockQuantity = item.Order_qty, // 假设子表有Quantity字段 SupplyQuantity = 0, OrderNo = mainOrder.Out_no, Dispatchertime = DateTime.Now, Remark = "" }; supplyTasks.Add(supplyTask); } // 批量插入供应任务 if (supplyTasks.Any()) { return BaseDal.Db.Insertable(supplyTasks).ExecuteCommand() > 0; } return false; } catch (Exception ex) { // 记录日志 Console.WriteLine($"创建供应任务失败:{ex.Message}"); return false; } } /// /// 生成随机任务编号(随机数 + 时间戳) /// /// 任务编号 private int GenerateTaskNumber() { // 生成4位随机数 Random random = new Random(Guid.NewGuid().GetHashCode()); int randomNum = random.Next(1000, 9999); // 1000-9999之间的随机数 // 组合成任务编号:TASK + 时间戳 + 随机数 return randomNum; } /// /// 出库单推送给 WCS /// /// public WebResponseContent EdiOut() { var responseContent = new WebResponseContent(); try { // 1. 查询符合条件的订单(表头=新建 && 包含有效明细) var outOrders = BaseDal.Db.CopyNew().Queryable() .Where(o => o.OutStatus == "新建" && o.Warehouse_no == WarehouseEnum.立库.ObjToInt().ToString("000")) .Includes(o => o.Details, d => d.MedicineGoods) .ToList(); // 2. 再过滤掉不符合条件的明细(只保留 Status=0 ) foreach (var order in outOrders) { order.Details = order.Details.Where(d => d.Status == 0).ToList(); } if (outOrders == null || !outOrders.Any()) { Console.WriteLine("没有符合条件的订单需要推送"); return responseContent.Error("没有符合条件的订单需要推送"); } foreach (var order in outOrders) { try { string materialCode = "YY";//默认值 //获取当前订单的第一个明细项 var firstDetail = order.Details.FirstOrDefault(); if (firstDetail?.MedicineGoods != null && !string.IsNullOrEmpty(firstDetail.MedicineGoods.MaterielErpType)) { //如果条件满足,将物料代码设置为第一个明细项对应的药品物料代码 materialCode = firstDetail.MedicineGoods.MaterielErpType; } // 3. 组装 DTO var ediDto = new TowcsDto.ToediOutInfo { customerCode = "905", materialCode = materialCode, externalOrderNo = order.Out_no, outOrderType = order.Out_type == "1" ? "10" : order.Out_type == "3" ? "20" : "30",//出库单类型是1就是正常的,3就是盘点 priority = 1, Is_cancel = 0, details = order.Details.Select(d => new TowcsDto.ToeOutdiInDetail { batchNo = d.Batch_num, productCode = d.Goods_no, productName = d.MedicineGoods?.MaterielName, productSpecifications = d.MedicineGoods?.MaterielModel, quantity = (int)d.Order_qty, //stocktakingDetails = order.Out_type == "3" // ? new List // { // new ToOutediInStock { palletCode = "FC00001", quantity = d.Order_qty.ToString() } // } // : null }).ToList() }; // 4. 调用接口 var url = "http://172.16.1.2:9357/file-admin/api/out/ediOut"; //var url = "http://127.0.0.1:4523/m2/5660322-5340849-default/363076920"; var result = HttpHelper.Post(url, ediDto.ToJsonString()); var resp = JsonConvert.DeserializeObject>(result); if (resp != null && resp.code == "0") { // 更新表头状态 BaseDal.Db.Updateable() .SetColumns(o => new Dt_DeliveryOrder { OutStatus = "开始" }) .Where(o => o.Id == order.Id) .ExecuteCommand(); // 更新明细状态 BaseDal.Db.Updateable() .SetColumns(d => new Dt_DeliveryOrderDetail { Status = 1, OotDetailStatus = "开始" }) .Where(d => d.DeliveryOrderId == order.Id && d.Status == 0) .ExecuteCommand(); Console.WriteLine($"订单 {order.Out_no} 推送成功"); } else { SendErrorToUpstream(3, order.Out_no, resp?.msg ?? "WCS 推送失败", ""); Console.WriteLine($"订单 {order.Out_no} 推送失败:{resp?.msg}"); } //删除全部状为已完成的明细和表头,移入历史表 } catch (Exception ex) { SendErrorToUpstream(3, order.Out_no, ex.Message, ""); Console.WriteLine($"订单 {order.Out_no} 推送异常:{ex.Message}"); } } return responseContent.OK("出库订单推送完成"); } catch (Exception ex) { Console.WriteLine("EdiOut 异常:" + ex.Message); return responseContent.Error("出库订单推送失败:" + ex.Message); } } //盘点 拿整个批次信息表的商品批号和商品编号来进行盘点 public WebResponseContent InventoryGood(string batchNo, string goodsNo) { var response = new WebResponseContent(); try { // 1️⃣ 查找指定批次与物料的库存信息 var batchInfo = BaseDal.Db.Queryable() .Where(x => x.BatchNo == batchNo && x.MaterielCode == goodsNo) .First(); if (batchInfo == null) return response.Error($"未找到该物料 [{goodsNo}] 批次 [{batchNo}] 的库存信息"); // 2️⃣ 组装请求 DTO(完全符合接口文档结构) var ediDto = new TowcsDto.ToediOutInfo { customerCode = "905", materialCode = "YY", // 物料类型CODE externalOrderNo = $"PDCK-{batchInfo.Id}", // 外部出库单号 outOrderType = "20", // 盘点出库单 priority = 1, Is_cancel = 0, details = new List { new TowcsDto.ToeOutdiInDetail { batchNo = batchInfo.BatchNo, productCode = batchInfo.MaterielCode, productName = batchInfo.MaterielName, productSpecifications = batchInfo.MaterielSpec, quantity = (int)batchInfo.SupplyQuantity, //stocktakingDetails = new List //{ // // 盘点明细可根据实际托盘拆分;此处示例仅1条 // new TowcsDto.ToOutediInStock // { // palletCode = "FC00001", // quantity = batchInfo.SupplyQuantity.ToString() // } //} } } }; // 3️⃣ 调用接口 string url = "http://172.16.1.2:9357/file-admin/api/out/ediOut"; var result = HttpHelper.Post(url, ediDto.ToJsonString()); var resp = JsonConvert.DeserializeObject>(result); // 4️⃣ 响应处理 if (resp == null) return response.Error("WCS 无响应"); if (resp.code != "0") return response.Error($"WCS返回失败: {resp.msg}"); return response.OK("盘点出库下发成功"); } catch (Exception ex) { return response.Error("盘点失败:" + ex.Message); } } /// /// 出库报完成接口 /// /// 出库单号 /// public WebResponseContent CompleteAllOutOrders() { var responseContent = new WebResponseContent(); try { #region 查找所有已完成出库单 var outorders = BaseDal.QueryData(x => x.OutStatus == "已完成").Select(x => x.Out_no).Distinct().ToList(); foreach (var outorder in outorders) { var Orders = BaseDal.Db.Queryable().Where(x => x.Out_no == outorder).Includes(x => x.Details).ToList(); if (!Orders.Where(x => x.OutStatus != "已完成").Any()) { BaseDal.Db.Ado.BeginTran(); BaseDal.DeleteAndMoveIntoHty(Orders, OperateTypeEnum.自动完成); foreach (var item in Orders) { _deliveryOrderDetailServices.Repository.DeleteAndMoveIntoHty(item.Details, OperateTypeEnum.自动完成); } var url = "http://121.37.118.63:80/GYZ2/95fck/outOrderOk"; var requestDate = new { order_no = outorder }; var result = HttpHelper.Post(url, requestDate.ToJsonString()); var response = JsonConvert.DeserializeObject(result); if (response.resultCode == "0") BaseDal.Db.Ado.CommitTran(); else { BaseDal.Db.Ado.RollbackTran(); SendErrorToUpstream(4, "", $"上游接口返回失败: {response.resultMsg}", outorder); } } } #endregion return responseContent.OK(); } catch (Exception ex) { BaseDal.Db.Ado.RollbackTran(); return responseContent.Error("批量处理失败:" + ex.Message); } } /// /// 推送异常信息给上游系统 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); } } /// /// 查询出库单列表 /// /// /// public WebResponseContent GetDeliveryOrders(SaveModel saveModel) { WebResponseContent content = new WebResponseContent(); try { int pageNo = saveModel.MainData["pageNo"].ObjToInt(); string warehouseCode = saveModel.MainData["warehouseId"].ToString(); string orderNo = saveModel.MainData["orderNo"].ToString(); List dt_ReceiveOrders = new List(); if (string.IsNullOrEmpty(orderNo)) { dt_ReceiveOrders = Db.Queryable().Where(x => (x.OutStatus == "新建" || x.OutStatus == "开始") && x.Warehouse_no == warehouseCode && x.Out_type != "3").Includes(x => x.Details).OrderByDescending(x => x.CreateDate).ToPageList(pageNo, 5); } else { dt_ReceiveOrders = Db.Queryable().Where(x => (x.Out_no.Contains(orderNo) || x.Client_no.Contains(orderNo)) && (x.OutStatus == "新建" || x.OutStatus == "开始") && x.Out_type != "3" && x.Warehouse_no == warehouseCode).OrderByDescending(x => x.CreateDate).Includes(x => x.Details).ToPageList(pageNo, 5); } content.OK(data: dt_ReceiveOrders); } catch (Exception) { throw; } return content; } /// /// 查询出库/盘点单详情 看出库单明细。 /// /// /// /// /// public WebResponseContent GetDeliveryOrderDetail(int pageNo, string orderNo, bool isPick) { WebResponseContent content = new WebResponseContent(); Dt_DeliveryOrder cabinOrder = new Dt_DeliveryOrder(); if (isPick) cabinOrder = Db.Queryable().Includes(x => x.Details).First(x => x.Out_no == orderNo && x.Out_type == "3"); else cabinOrder = Db.Queryable().Includes(x => x.Details).First(x => x.Out_no == orderNo && x.Out_type != "3"); //List? cabinOrderDetails = cabinOrder.Details?.Where(x => x.Reservoirarea == pageNo.ToString()).ToList(); List? cabinOrderDetails = cabinOrder.Details?.Where(x => x.Status == 2).ToList(); content.OK(data: cabinOrderDetails); return content; } public WebResponseContent OutFinish(SaveModel saveModel) { WebResponseContent content = new WebResponseContent(); try { var LocationCode = saveModel.MainData["locationCode"].ToString(); var TaskId = saveModel.MainData["taskId"].ObjToInt(); Dt_SupplyTask supplyTask = _supplyTaskService.Repository.QueryFirst(x => x.TaskId == TaskId && x.TaskStatus == SupplyStatusEnum.NewOut.ObjToInt()); if (supplyTask == null) throw new Exception("当前出库任务已完成"); if (supplyTask.LocationCode != LocationCode) throw new Exception($"当前出库货位【{LocationCode}】与任务分配货位不匹配"); OutTaskFinish(supplyTask); } catch (Exception ex) { content.Error(ex.Message); } return content; } public WebResponseContent OutTaskFinish(Dt_SupplyTask supplyTask) { WebResponseContent content = new WebResponseContent(); try { Dt_DeliveryOrder cabinOrder = BaseDal.Db.Queryable().Where(x => x.Out_no == supplyTask.OrderNo && x.Warehouse_no == supplyTask.WarehouseCode).Includes(x => x.Details).First(); if (cabinOrder == null) return WebResponseContent.Instance.Error($"出库单已完成"); Dt_DeliveryOrderDetail cabinOrderDetail = cabinOrder.Details.Where(x => x.Batch_num == supplyTask.BatchNo && x.Reservoirarea == supplyTask.WarehouseCode && x.Goods_no == supplyTask.MaterielCode).First(); if (cabinOrderDetail == null) return WebResponseContent.Instance.Error($"出库单明细已完成"); Dt_MaterielInfo materielInfo = _basicService.MaterielInfoService.Repository.QueryFirst(x => x.MaterielCode == cabinOrderDetail.Goods_no); if (materielInfo == null) return WebResponseContent.Instance.Error($"请维护物料编号【{cabinOrderDetail.Goods_no}】的物料信息"); cabinOrderDetail.Order_Outqty += supplyTask.StockQuantity; if (cabinOrderDetail.Order_Outqty > cabinOrderDetail.Order_qty) return WebResponseContent.Instance.Error($"出库数量不可超出单据数量"); #region 处理出库单,货位,库存,库存批次信息,出库任务 _unitOfWorkManage.BeginTran(); #region 出库单 cabinOrder.OutStatus = "开始"; cabinOrderDetail.OotDetailStatus = "开始"; if (cabinOrderDetail.Order_Outqty == cabinOrderDetail.Order_qty) { cabinOrderDetail.OotDetailStatus = "已完成"; //_deliveryOrderDetailServices.Repository.DeleteAndMoveIntoHty(cabinOrderDetail, OperateTypeEnum.自动完成); } _deliveryOrderDetailServices.Repository.UpdateData(cabinOrderDetail); var cabinOrder1 = BaseDal.Db.Queryable().Where(x => x.Out_no == cabinOrder.Out_no && x.Warehouse_no == supplyTask.WarehouseCode && x.Out_type != "3").Includes(x => x.Details).First(); if (!cabinOrder1.Details.Where(x => x.OotDetailStatus != "已完成").Any()) cabinOrder.OutStatus = "已完成"; Repository.UpdateData(cabinOrder); #endregion #region 库存 Dt_InventoryInfo inventoryInfo = _inventoryInfoService.Repository.QueryFirst(x => x.BatchNo == cabinOrderDetail.Batch_num && x.MaterielCode == cabinOrderDetail.Goods_no && x.LocationCode == supplyTask.LocationCode); if (inventoryInfo == null) return WebResponseContent.Instance.Error($"未找到货位【{supplyTask.LocationCode}】的库存信息"); inventoryInfo.StockQuantity -= supplyTask.StockQuantity; inventoryInfo.OutboundQuantity -= supplyTask.StockQuantity; if (inventoryInfo.StockQuantity <= 0) _inventoryInfoService.DeleteData(inventoryInfo); else _inventoryInfoService.UpdateData(inventoryInfo); #endregion #region 货位 if (supplyTask.WarehouseCode != WarehouseEnum.立库.ObjToInt().ToString("000")) { var location = _basicService.LocationInfoService.Repository.QueryFirst(x => x.LocationCode == supplyTask.LocationCode); if (location == null) return WebResponseContent.Instance.Error($"请维护货位编号【{supplyTask.LocationCode}】的货位信息"); //if (location.EnableStatus == EnableStatusEnum.Disable.ObjToInt()) // return WebResponseContent.Instance.Error($"货位编号【{supplyTask.LocationCode}】已禁用,请恢复正常再使用"); Dt_InventoryInfo inventoryInfo1 = _inventoryInfoService.Repository.QueryFirst(x => x.LocationCode == supplyTask.LocationCode); if (inventoryInfo1 == null) { location.LocationStatus = LocationStatusEnum.Free.ObjToInt(); _basicService.LocationInfoService.UpdateData(location); } } #endregion //_supplyTaskService.UpdateData(supplyTask); supplyTask.TaskNum = cabinOrderDetail.Id; supplyTask.TaskStatus = SupplyStatusEnum.OutFinish.ObjToInt(); _supplyTaskService.Repository.DeleteAndMoveIntoHty(supplyTask, OperateTypeEnum.人工完成); #region 库存批次 Dt_Inventory_Batch inventory_Batch = _inventory_BatchServices.Repository.QueryFirst(x => x.BatchNo == inventoryInfo.BatchNo && x.MaterielCode == inventoryInfo.MaterielCode); if (inventory_Batch != null) { inventory_Batch.StockQuantity -= supplyTask.StockQuantity; inventory_Batch.OutboundQuantity -= supplyTask.StockQuantity; if (inventory_Batch.StockQuantity <= 0) _inventory_BatchServices.DeleteData(inventory_Batch); else _inventory_BatchServices.UpdateData(inventory_Batch); } #endregion if (supplyTask.WarehouseCode == WarehouseEnum.立库.ObjToInt().ToString("000")) CreateAllocatInOut(materielInfo);//创建调拨任务 _unitOfWorkManage.CommitTran(); #endregion content.OK(); } catch (Exception ex) { content.Error(ex.Message); } return content; } /// /// 平库人工拣料出库处理(即人工扫码出库时调用) /// /// /// public WebResponseContent MatPicking(SaveModel saveModel) { WebResponseContent content = new WebResponseContent(); try { var LocationCode = saveModel.MainData["LocationCode"].ToString(); var orderNo = saveModel.MainData["orderNo"].ToString(); var batchNo = saveModel.MainData["batchNo"].ToString(); var Inqty = saveModel.MainData["Inqty"].ObjToInt(); var warehouseCode = saveModel.MainData["warehouseCode"].ToString(); Dt_DeliveryOrder cabinOrder = BaseDal.Db.Queryable().Where(x => x.Out_no == orderNo && x.Warehouse_no == warehouseCode && x.Out_type != "3").Includes(x => x.Details).First(); if (cabinOrder == null) return WebResponseContent.Instance.Error($"出库单已完成"); Dt_DeliveryOrderDetail cabinOrderDetail = cabinOrder.Details.Where(x => x.Batch_num == batchNo && x.Reservoirarea == warehouseCode).First(); if (cabinOrderDetail == null) return WebResponseContent.Instance.Error($"出库单明细已完成"); Dt_MaterielInfo materielInfo = _basicService.MaterielInfoService.Repository.QueryFirst(x => x.MaterielCode == cabinOrderDetail.Goods_no); if (materielInfo == null) return WebResponseContent.Instance.Error($"请维护物料编号【{cabinOrderDetail.Goods_no}】的物料信息"); cabinOrderDetail.Order_Outqty += Inqty; if (cabinOrderDetail.Order_Outqty > cabinOrderDetail.Order_qty) return WebResponseContent.Instance.Error($"出库数量不可超出单据数量"); #region 处理出库单,货位,库存,库存批次信息 _unitOfWorkManage.BeginTran(); #region 出库单 cabinOrder.OutStatus = "开始"; cabinOrderDetail.OotDetailStatus = "开始"; if (cabinOrderDetail.Order_Outqty == cabinOrderDetail.Order_qty) { cabinOrderDetail.OotDetailStatus = "已完成"; _deliveryOrderDetailServices.Repository.DeleteAndMoveIntoHty(cabinOrderDetail, OperateTypeEnum.自动完成); } else { _deliveryOrderDetailServices.Repository.UpdateData(cabinOrderDetail); } var cabinOrder1 = BaseDal.Db.Queryable().Where(x => x.Out_no == cabinOrder.Out_no && x.Out_type != "3").Includes(x => x.Details).First(); if (cabinOrder1.Details == null || cabinOrder1.Details.Count < 1) cabinOrder.OutStatus = "已完成"; Repository.UpdateData(cabinOrder); #endregion #region 库存 Dt_InventoryInfo inventoryInfo = _inventoryInfoService.Repository.QueryFirst(x => x.BatchNo == cabinOrderDetail.Batch_num && x.MaterielCode == cabinOrderDetail.Goods_no && x.LocationCode == LocationCode); if (inventoryInfo == null) return WebResponseContent.Instance.Error($"未找到货位【{LocationCode}】的库存信息"); inventoryInfo.StockQuantity -= Inqty; if (inventoryInfo.StockQuantity <= 0) _inventoryInfoService.DeleteData(inventoryInfo); else _inventoryInfoService.UpdateData(inventoryInfo); #endregion #region 货位 var location = _basicService.LocationInfoService.Repository.QueryFirst(x => x.LocationCode == LocationCode); if (location == null) return WebResponseContent.Instance.Error($"请维护货位编号【{LocationCode}】的货位信息"); if (location.EnableStatus == EnableStatusEnum.Disable.ObjToInt()) return WebResponseContent.Instance.Error($"货位编号【{LocationCode}】已禁用,请恢复正常再使用"); Dt_InventoryInfo inventoryInfo1 = _inventoryInfoService.Repository.QueryFirst(x => x.LocationCode == LocationCode); if (inventoryInfo1 == null) { location.LocationStatus = LocationStatusEnum.Free.ObjToInt(); _basicService.LocationInfoService.UpdateData(location); } #endregion #region 任务记录 Dt_SupplyTask supplyTask = new Dt_SupplyTask() { WarehouseCode = cabinOrderDetail.Reservoirarea, BatchNo = inventoryInfo.BatchNo, MaterielName = inventoryInfo.MaterielName, MaterielCode = inventoryInfo.MaterielCode, MaterielSpec = inventoryInfo.MaterielSpec, TaskStatus = SupplyStatusEnum.OutFinish.ObjToInt(), TaskType = TaskTypeEnum.OutPick.ObjToInt(), CreateDate = DateTime.Now, Creater = App.User.UserName, LocationCode = location.LocationCode, OrderNo = cabinOrder.Out_no, StockQuantity = Inqty, SupplyQuantity = 0, Remark = "出库" }; _supplyTaskService.AddData(supplyTask); #endregion #region 库存批次 Dt_Inventory_Batch inventory_Batch = _inventory_BatchServices.Repository.QueryFirst(x => x.BatchNo == inventoryInfo.BatchNo && x.MaterielCode == inventoryInfo.MaterielCode); if (inventory_Batch != null) { inventory_Batch.StockQuantity -= Inqty; if (inventory_Batch.StockQuantity <= 0) _inventory_BatchServices.DeleteData(inventory_Batch); else _inventory_BatchServices.UpdateData(inventory_Batch); } #endregion _unitOfWorkManage.CommitTran(); #endregion content.OK(cabinOrderDetail.Order_Outqty.ToString()); } catch (Exception ex) { _unitOfWorkManage.RollbackTran(); content.Error(ex.Message); } return content; } } }