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.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_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 { private readonly ICabinOrderServices _cabinOrderServices; 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 ISupplyTaskHtyService _supplyTaskHtyService; private readonly ITacticsService _tacticsService; public IRepository Repository => BaseDal; public DeliveryOrderServices(IRepository BaseDal, IBasicService basicService, IUnitOfWorkManage unitOfWorkManage, IInventory_BatchServices inventory_BatchServices, IInventoryInfoService inventoryInfoService, IDeliveryOrderDetailServices deliveryOrderDetailServices, ISupplyTaskService supplyTaskService, ICabinOrderServices cabinOrderServices, ITacticsService tacticsService, ISupplyTaskHtyService supplyTaskHtyService) : base(BaseDal) { _basicService = basicService; _unitOfWorkManage = unitOfWorkManage; _deliveryOrderDetailServices = deliveryOrderDetailServices; _supplyTaskService = supplyTaskService; _inventory_BatchServices = inventory_BatchServices; _inventoryInfoService = inventoryInfoService; _cabinOrderServices = cabinOrderServices; _tacticsService = tacticsService; _supplyTaskHtyService = supplyTaskHtyService; } #region 创建出库单 /// /// 创建出库单 /// /// /// public WebResponseContent CreateOutboundOrder(UpstramOutOrderInfo outorder) { WebResponseContent webResponseContent = new WebResponseContent(); try { Dt_Tactics tactics = _tacticsService.Repository.QueryFirst(x => x.TacticeName == "出库策略"); #region 特殊库房出库 string WareCodeMJ = WarehouseEnum.麻精库.ObjToInt().ToString("000"); string WareCodeLD = WarehouseEnum.冷冻库.ObjToInt().ToString("000"); if (outorder.warehouse_no == WareCodeMJ || outorder.warehouse_no == WareCodeLD) { #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 { Reservoirarea = outorder.warehouse_no, 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 处理库存、库存批次、添加出库任务 List supplyTasks = new List(); foreach (var item in entityOrder.Details) { Dt_Inventory_Batch inventory_Batch = _inventory_BatchServices.Repository.QueryFirst(x => x.MaterielCode == item.Goods_no && x.BatchNo == item.Batch_num); if (inventory_Batch == null) throw new Exception($"未找到出库单号【{entityOrder.Out_no}】中物料编号【{item.Goods_no}】物料批次【{item.Batch_num}】的库存批次信息"); if (inventory_Batch.AvailableQuantity < item.Order_qty) throw new Exception($"出库单号【{entityOrder.Out_no}】中物料编号【{item.Goods_no}】物料批次【{item.Batch_num}】的库存批次信息可用数量不足"); inventory_Batch.AvailableQuantity -= item.Order_qty; inventory_Batch.OutboundQuantity += item.Order_qty; List dt_InventoryInfos = _inventoryInfoService.Repository.QueryData(x => x.MaterielCode == item.Goods_no && x.BatchNo == item.Batch_num && x.StockStatus == StockStatusEmun.入库完成.ObjToInt() && x.AvailableQuantity > 0 && x.WarehouseCode == item.Reservoirarea); if (dt_InventoryInfos.Count < 1) throw new Exception($"出库单号【{entityOrder.Out_no}】中物料编号【{item.Goods_no}】物料批次【{item.Batch_num}】的库存当前状态不可出库"); #region 按出库策略查找库存 if (tactics.SelectTactice == TacticsEnum.ComeOutonFirstTime.ObjToInt()) dt_InventoryInfos = dt_InventoryInfos.OrderBy(x => x.ValidityPeriod).ToList(); else dt_InventoryInfos = dt_InventoryInfos.OrderBy(x => x.InDate).ToList(); #endregion var Order_qty = item.Order_qty;//出库单数量 foreach (var InventoryInfo in dt_InventoryInfos) { if (Order_qty <= 0) break; if (InventoryInfo.AvailableQuantity <= Order_qty) { Order_qty -= InventoryInfo.AvailableQuantity; InventoryInfo.OutboundQuantity += InventoryInfo.AvailableQuantity; Dt_SupplyTask supplyTask = new Dt_SupplyTask() { WarehouseCode = InventoryInfo.WarehouseCode, BatchNo = InventoryInfo.BatchNo, MaterielName = InventoryInfo.MaterielName, MaterielCode = InventoryInfo.MaterielCode, MaterielSpec = InventoryInfo.MaterielSpec, TaskStatus = SupplyStatusEnum.NewOut.ObjToInt(), TaskType = outorder.order_type == "1" ? TaskTypeEnum.Out.ObjToInt() : TaskTypeEnum.InReturn.ObjToInt(), CreateDate = DateTime.Now, Creater = App.User.UserName ?? "System", LocationCode = InventoryInfo.LocationCode, OrderNo = entityOrder.Out_no, StockQuantity = InventoryInfo.AvailableQuantity, SupplyQuantity = 0, Remark = "出库" }; supplyTasks.Add(supplyTask); InventoryInfo.AvailableQuantity = 0; } else { InventoryInfo.AvailableQuantity -= Order_qty; InventoryInfo.OutboundQuantity += Order_qty; Dt_SupplyTask supplyTask = new Dt_SupplyTask() { WarehouseCode = InventoryInfo.WarehouseCode, BatchNo = InventoryInfo.BatchNo, MaterielName = InventoryInfo.MaterielName, MaterielCode = InventoryInfo.MaterielCode, MaterielSpec = InventoryInfo.MaterielSpec, TaskStatus = SupplyStatusEnum.NewOut.ObjToInt(), TaskType = outorder.order_type == "1" ? TaskTypeEnum.Out.ObjToInt() : TaskTypeEnum.InReturn.ObjToInt(), CreateDate = DateTime.Now, Creater = App.User.UserName ?? "System", LocationCode = InventoryInfo.LocationCode, OrderNo = entityOrder.Out_no, StockQuantity = Order_qty, SupplyQuantity = 0, Remark = "出库" }; supplyTasks.Add(supplyTask); Order_qty = 0; } } _inventory_BatchServices.Repository.UpdateData(inventory_Batch); _inventoryInfoService.Repository.UpdateData(dt_InventoryInfos); } _supplyTaskService.AddData(supplyTasks); #endregion } #endregion else { string WareCodeDJ = WarehouseEnum.大件库.ObjToInt().ToString("000"); string WareCodeLK = WarehouseEnum.立库.ObjToInt().ToString("000"); #region 创建大件库、立库出库头表 var entityOrder = new Dt_DeliveryOrder { Out_no = outorder.order_no, Out_type = outorder.order_type, OutStatus = "新建", Client_name = outorder.client_name, Account_time = outorder.account_time, Client_no = outorder.client_no, Warehouse_no = WareCodeDJ, Details = new List() }; var entityOrderLK = new Dt_DeliveryOrder { Out_no = outorder.order_no, Out_type = outorder.order_type, OutStatus = "新建", Client_name = outorder.client_name, Account_time = outorder.account_time, Client_no = outorder.client_no, Warehouse_no = WareCodeLK, Details = new List() }; #endregion #region 查找库存 foreach (var detail in outorder.details) { #region 查询库存批次和库存 Dt_Inventory_Batch inventory_Batch = _inventory_BatchServices.Repository.QueryFirst(x => x.MaterielCode == detail.goods_no && x.BatchNo == detail.batch_num); if (inventory_Batch == null) throw new Exception($"未找到出库单号【{outorder.order_no}】中物料编号【{detail.goods_no}】物料批次【{detail.batch_num}】的库存批次信息"); if (inventory_Batch.AvailableQuantity < detail.order_qty) throw new Exception($"出库单号【{outorder.order_no}】中物料编号【{detail.goods_no}】物料批次【{detail.batch_num}】的库存批次信息可用数量不足"); inventory_Batch.AvailableQuantity -= detail.order_qty; inventory_Batch.OutboundQuantity += detail.order_qty; List dt_InventoryInfos = _inventoryInfoService.Repository.QueryData(x => x.MaterielCode == inventory_Batch.MaterielCode && x.BatchNo == inventory_Batch.BatchNo && x.AvailableQuantity > 0 && (x.WarehouseCode == WareCodeDJ || x.WarehouseCode == WareCodeLK)); if (dt_InventoryInfos.Count < 1) throw new Exception($"出库单号【{outorder.order_no}】中物料编号【{detail.goods_no}】物料批次【{detail.batch_num}】的库存当前状态不可出库"); #endregion #region 按出库策略查找库存 if (tactics.SelectTactice == TacticsEnum.ComeOutonFirstTime.ObjToInt()) dt_InventoryInfos = dt_InventoryInfos.OrderBy(x => x.ValidityPeriod).ToList(); else dt_InventoryInfos = dt_InventoryInfos.OrderBy(x => x.InDate).ToList(); #endregion var Order_qty = Math.Abs(detail.order_qty);//出库单数量 #region 根据物料编码查询物料信息 Dt_MaterielInfo materielInfo = _basicService.MaterielInfoService.Repository.QueryFirst(x => x.MaterielCode == detail.goods_no); if (materielInfo == null) throw new Exception($"未找到药品编码【{detail.goods_no}】的信息"); if (!Enum.IsDefined(typeof(MaterielSourceTypeEnum), materielInfo.MaterielSourceType)) throw new Exception($"请设置药品编号【{detail.goods_no}】的属性分类"); if (materielInfo.BoxQty < 1) throw new Exception($"请设置药品编号【{detail.goods_no}】的箱规数量"); #endregion #region 大件 if (materielInfo.MaterielSourceType == MaterielSourceTypeEnum.PurchasePart)//如果物料是大件 { #region 添加出库详情 Dt_DeliveryOrderDetail orderDetail = new Dt_DeliveryOrderDetail() { Reservoirarea = entityOrder.Warehouse_no, Goods_no = detail.goods_no, Order_qty = detail.order_qty, Batch_num = detail.batch_num, Exp_date = detail.exp_date, OotDetailStatus = "新建", Order_Outqty = 0, Status = 2 }; entityOrder.Details.Add(orderDetail); #endregion List supplyTasks = new List(); #region 计算库存、添加出库任务 foreach (var InventoryInfo in dt_InventoryInfos) { if (Order_qty <= 0) break; if (InventoryInfo.AvailableQuantity < Order_qty) { Order_qty -= InventoryInfo.AvailableQuantity; InventoryInfo.OutboundQuantity += InventoryInfo.AvailableQuantity; Dt_SupplyTask supplyTask = new Dt_SupplyTask() { WarehouseCode = InventoryInfo.WarehouseCode, BatchNo = InventoryInfo.BatchNo, MaterielName = InventoryInfo.MaterielName, MaterielCode = InventoryInfo.MaterielCode, MaterielSpec = InventoryInfo.MaterielSpec, TaskStatus = SupplyStatusEnum.NewOut.ObjToInt(), TaskType = outorder.order_type == "1" ? TaskTypeEnum.Out.ObjToInt() : TaskTypeEnum.InReturn.ObjToInt(), CreateDate = DateTime.Now, Creater = App.User.UserName ?? "System", LocationCode = InventoryInfo.LocationCode, OrderNo = entityOrder.Out_no, StockQuantity = InventoryInfo.AvailableQuantity, SupplyQuantity = 0, Remark = "出库" }; supplyTasks.Add(supplyTask); InventoryInfo.AvailableQuantity = 0; } else { InventoryInfo.AvailableQuantity -= Order_qty; InventoryInfo.OutboundQuantity += Order_qty; Dt_SupplyTask supplyTask = new Dt_SupplyTask() { WarehouseCode = InventoryInfo.WarehouseCode, BatchNo = InventoryInfo.BatchNo, MaterielName = InventoryInfo.MaterielName, MaterielCode = InventoryInfo.MaterielCode, MaterielSpec = InventoryInfo.MaterielSpec, TaskStatus = SupplyStatusEnum.NewOut.ObjToInt(), TaskType = outorder.order_type == "1" ? TaskTypeEnum.Out.ObjToInt() : TaskTypeEnum.InReturn.ObjToInt(), CreateDate = DateTime.Now, Creater = App.User.UserName ?? "System", LocationCode = InventoryInfo.LocationCode, OrderNo = entityOrder.Out_no, StockQuantity = Order_qty, SupplyQuantity = 0, Remark = "出库" }; supplyTasks.Add(supplyTask); Order_qty = 0; } } #endregion _inventory_BatchServices.Repository.UpdateData(inventory_Batch); _inventoryInfoService.Repository.UpdateData(dt_InventoryInfos); _supplyTaskService.AddData(supplyTasks); } #endregion else { List supplyTasks = new List(); Dt_DeliveryOrderDetail orderDetail = null; Dt_DeliveryOrderDetail orderDetailLK = null; var ys = Order_qty % materielInfo.BoxQty; //不能整除箱规的散件数 var xs = (int)(Order_qty / materielInfo.BoxQty);//保留整数 #region 散件优先分配立库 if (ys > 0) { orderDetailLK = new Dt_DeliveryOrderDetail() { Reservoirarea = entityOrderLK.Warehouse_no, Goods_no = detail.goods_no, Order_qty = ys, Batch_num = detail.batch_num, Exp_date = detail.exp_date, OotDetailStatus = "新建", Order_Outqty = 0, Status = 0 }; } #endregion #region 整件优先分配大件库,计划库存,添加出库任务 foreach (var item in dt_InventoryInfos.Where(x => x.WarehouseCode == WareCodeDJ)) { if (xs <= 0) break; decimal outqty = 0; while (item.AvailableQuantity > 0 && xs > 0) { xs--; if (orderDetail == null) { orderDetail = new Dt_DeliveryOrderDetail() { Reservoirarea = entityOrder.Warehouse_no, Goods_no = detail.goods_no, Order_qty = materielInfo.BoxQty, Batch_num = detail.batch_num, Exp_date = detail.exp_date, OotDetailStatus = "新建", Order_Outqty = 0, Status = 2 }; item.AvailableQuantity -= materielInfo.BoxQty; item.OutboundQuantity += materielInfo.BoxQty; outqty += materielInfo.BoxQty; } else { orderDetail.Order_qty += materielInfo.BoxQty; item.AvailableQuantity -= materielInfo.BoxQty; item.OutboundQuantity += materielInfo.BoxQty; outqty += materielInfo.BoxQty; } } Dt_SupplyTask supplyTask = new Dt_SupplyTask() { WarehouseCode = item.WarehouseCode, BatchNo = item.BatchNo, MaterielName = item.MaterielName, MaterielCode = item.MaterielCode, MaterielSpec = item.MaterielSpec, TaskStatus = SupplyStatusEnum.NewOut.ObjToInt(), TaskType = outorder.order_type == "1" ? TaskTypeEnum.Out.ObjToInt() : TaskTypeEnum.InReturn.ObjToInt(), CreateDate = DateTime.Now, Creater = App.User.UserName ?? "System", LocationCode = item.LocationCode, OrderNo = entityOrder.Out_no, StockQuantity = outqty, SupplyQuantity = 0, Remark = "出库" }; supplyTasks.Add(supplyTask); _inventoryInfoService.Repository.UpdateData(item); } #endregion #region 分配完大件库如果还有箱数,再选择分配立库 if (xs > 0) { if (orderDetailLK == null) { orderDetailLK = new Dt_DeliveryOrderDetail() { Reservoirarea = entityOrderLK.Warehouse_no, Goods_no = detail.goods_no, Order_qty = xs * materielInfo.BoxQty, Batch_num = detail.batch_num, Exp_date = detail.exp_date, OotDetailStatus = "新建", Order_Outqty = 0, Status = 0 }; } else { orderDetailLK.Order_qty += xs * materielInfo.BoxQty; } } #endregion #region 立库出库单,修改立库库存,添加立库出库任务 if (orderDetailLK != null) { #region 添加出库任务、修改库存信息 Dt_InventoryInfo inventoryInfo = dt_InventoryInfos.Where(x => x.WarehouseCode == WareCodeLK).First(); inventoryInfo.AvailableQuantity -= orderDetailLK.Order_qty; inventoryInfo.OutboundQuantity += orderDetailLK.Order_qty; Dt_SupplyTask supplyTask = new Dt_SupplyTask() { WarehouseCode = inventoryInfo.WarehouseCode, BatchNo = inventoryInfo.BatchNo, MaterielName = inventoryInfo.MaterielName, MaterielCode = inventoryInfo.MaterielCode, MaterielSpec = inventoryInfo.MaterielSpec, TaskStatus = SupplyStatusEnum.NewOut.ObjToInt(), TaskType = outorder.order_type == "1" ? TaskTypeEnum.Out.ObjToInt() : TaskTypeEnum.InReturn.ObjToInt(), CreateDate = DateTime.Now, Creater = App.User.UserName ?? "System", LocationCode = inventoryInfo.LocationCode, OrderNo = entityOrder.Out_no, StockQuantity = orderDetailLK.Order_qty, SupplyQuantity = 0, Remark = "出库" }; supplyTasks.Add(supplyTask); #endregion _inventoryInfoService.Repository.UpdateData(inventoryInfo); entityOrderLK.Details.Add(orderDetailLK); } #endregion if (orderDetail != null) entityOrder.Details.Add(orderDetail); _inventory_BatchServices.Repository.UpdateData(inventory_Batch); _supplyTaskService.AddData(supplyTasks); } } if (entityOrder.Details.Count > 0) BaseDal.Db.InsertNav(entityOrder).Include(x => x.Details).ExecuteCommand(); if (entityOrderLK.Details.Count > 0) BaseDal.Db.InsertNav(entityOrderLK).Include(x => x.Details).ExecuteCommand(); #endregion } } catch (Exception ex) { webResponseContent.Error(ex.Message); } return webResponseContent; } #endregion #region 创建盘亏出库单 public WebResponseContent CreateCheckOutOrder(UpstramOutOrderInfo order) { WebResponseContent content = new WebResponseContent(); try { string WareCodeMJ = WarehouseEnum.麻精库.ObjToInt().ToString("000"); string WareCodeLD = WarehouseEnum.冷冻库.ObjToInt().ToString("000"); #region 特殊库房 if (order.warehouse_no == WareCodeMJ || order.warehouse_no == WareCodeLD) { #region 库存、库存批次平账 foreach (var item in order.details) { //找库存批次信息 Dt_Inventory_Batch inventory_Batch = _inventory_BatchServices.Repository.QueryFirst(x => x.MaterielCode == item.goods_no && x.BatchNo == item.batch_num); var Qty = Math.Abs(inventory_Batch.StockQuantity - inventory_Batch.SupplyQuantity); if (Qty != item.order_qty) throw new Exception($"盘亏出库单【{order.order_no}】物料编号【{item.goods_no}】物料批次【{item.batch_num}】的盘亏数量有误"); //找所有库存 List inventoryInfos = _inventoryInfoService.Repository.QueryData(x => x.MaterielCode == inventory_Batch.MaterielCode && x.BatchNo == inventory_Batch.BatchNo); foreach (var inventoryInfo in inventoryInfos) { #region 添加盘亏出库任务 if (inventoryInfo.StockQuantity != inventoryInfo.SupplyQuantity) { 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 = order.order_no, StockQuantity = Math.Abs(inventoryInfo.StockQuantity - inventoryInfo.SupplyQuantity), SupplyQuantity = 0, Remark = "盘亏入库" }; _supplyTaskHtyService.AddData(supplyTask_Hty); } #endregion inventoryInfo.StockQuantity = inventoryInfo.SupplyQuantity; inventoryInfo.SupplyQuantity = 0; inventoryInfo.StockStatus = StockStatusEmun.入库完成.ObjToInt(); } inventory_Batch.StockQuantity = inventory_Batch.SupplyQuantity; inventory_Batch.SupplyQuantity = 0; _inventoryInfoService.UpdateData(inventoryInfos); _inventory_BatchServices.UpdateData(inventory_Batch); } #endregion #region 创建盘点单 var entityOrder = new Dt_DeliveryOrder { Out_no = order.order_no, Out_type = order.order_type, Client_no = order.client_no, Client_name = order.client_name, OutStatus = "已完成", Account_time = order.account_time, Warehouse_no = order.warehouse_no, Details = order.details.Select(d => new Dt_DeliveryOrderDetail { Goods_no = d.goods_no, Order_qty = Math.Abs(d.order_qty), Order_Outqty = Math.Abs(d.order_qty), Batch_num = d.batch_num, Exp_date = d.exp_date, Reservoirarea = order.warehouse_no, OotDetailStatus = "已完成", Status = 2, }).ToList() }; Repository.AddData(entityOrder); #endregion } #endregion else { string WareCodeLK = WarehouseEnum.立库.ObjToInt().ToString("000"); string WareCodeDJ = WarehouseEnum.大件库.ObjToInt().ToString("000"); foreach (var item in order.details) { //找库存批次信息 Dt_Inventory_Batch inventory_Batch = _inventory_BatchServices.Repository.QueryFirst(x => x.MaterielCode == item.goods_no && x.BatchNo == item.batch_num); var Qty = Math.Abs(inventory_Batch.StockQuantity - inventory_Batch.SupplyQuantity); if (Qty != item.order_qty) throw new Exception($"盘盈入库单【{order.order_no}】物料编号【{item.goods_no}】物料批次【{item.batch_num}】的盘盈数量有误"); //找所有库存 List inventoryInfos = _inventoryInfoService.Repository.QueryData(x => x.MaterielCode == inventory_Batch.MaterielCode && x.BatchNo == inventory_Batch.BatchNo); //获取立库盘点差异数 var inventoryLK = inventoryInfos.Where(x => x.WarehouseCode == WareCodeLK).First(); var LkQty = Math.Abs(inventoryLK.StockQuantity - inventoryLK.SupplyQuantity); //获取大件库盘点差异数 var inventoryDJ = inventoryInfos.Where(x => x.WarehouseCode == WareCodeDJ).ToList(); var DJQty = Math.Abs(inventoryDJ.Sum(x => x.StockQuantity) - inventoryDJ.Sum(x => x.SupplyQuantity)); if (LkQty + DJQty != Qty) throw new Exception($"【{order.order_no}】物料编号【{item.goods_no}】物料批次【{item.batch_num}】的物料信息与物料批次信息盘盈数量不符"); if (LkQty == 0)//立库无差异 { #region 库存、库存批次平账 foreach (var inventoryInfo in inventoryInfos) { #region 添加盘亏出库任务 if (inventoryInfo.StockQuantity != inventoryInfo.SupplyQuantity) { 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 = order.order_no, StockQuantity = Math.Abs(inventoryInfo.StockQuantity - inventoryInfo.SupplyQuantity), SupplyQuantity = 0, Remark = "盘亏入库" }; _supplyTaskHtyService.AddData(supplyTask_Hty); } #endregion inventoryInfo.StockQuantity = inventoryInfo.SupplyQuantity; inventoryInfo.SupplyQuantity = 0; inventoryInfo.StockStatus = StockStatusEmun.入库完成.ObjToInt(); } _inventoryInfoService.UpdateData(inventoryInfos); inventory_Batch.StockQuantity = inventory_Batch.SupplyQuantity; inventory_Batch.SupplyQuantity = 0; _inventory_BatchServices.UpdateData(inventory_Batch); #endregion #region 创建大件库盘点单 var entityOrder = new Dt_DeliveryOrder { Out_no = order.order_no, Out_type = order.order_type, Client_no = order.client_no, Account_time = order.account_time, OutStatus = "已完成", Client_name = order.client_name, Warehouse_no = WareCodeDJ, Details = order.details.Select(d => new Dt_DeliveryOrderDetail { Goods_no = d.goods_no, Order_qty = Math.Abs(d.order_qty), Order_Outqty = Math.Abs(d.order_qty), Batch_num = d.batch_num, Exp_date = d.exp_date, Reservoirarea = WareCodeDJ, OotDetailStatus = "已完成", Status = 2, }).ToList() }; Repository.AddData(entityOrder); #endregion } else { #region 大件库库存平账 inventoryInfos = inventoryInfos.Where(x => x.WarehouseCode == WareCodeDJ).ToList(); foreach (var inventoryInfo in inventoryInfos) { #region 添加盘亏出库任务 if (inventoryInfo.StockQuantity != inventoryInfo.SupplyQuantity) { 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 = order.order_no, StockQuantity = Math.Abs(inventoryInfo.StockQuantity - inventoryInfo.SupplyQuantity), SupplyQuantity = 0, Remark = "盘盈入库" }; _supplyTaskHtyService.AddData(supplyTask_Hty); } #endregion inventoryInfo.StockQuantity = inventoryInfo.SupplyQuantity; inventoryInfo.SupplyQuantity = 0; inventoryInfo.StockStatus = StockStatusEmun.入库完成.ObjToInt(); } _inventoryInfoService.UpdateData(inventoryInfos); #endregion #region 创建大件库盘点单 if (DJQty != 0) { var cabinOrder = new Dt_DeliveryOrder { Out_no = order.order_no, Out_type = order.order_type, Client_name = order.client_name, Account_time = order.account_time, OutStatus = "已完成", Client_no = order.client_no, Warehouse_no = WareCodeDJ, Details = order.details.Select(d => new Dt_DeliveryOrderDetail { Goods_no = d.goods_no, Order_qty = DJQty, Order_Outqty = DJQty, Batch_num = d.batch_num, Exp_date = d.exp_date, Reservoirarea = WareCodeDJ, OotDetailStatus = "已完成", Status = 2, }).ToList() }; Repository.AddData(cabinOrder); } #endregion #region 创建立库盘点单 var entityOrder = new Dt_DeliveryOrder { Out_no = order.order_no, Out_type = order.order_type, Client_no = order.client_no, Account_time = order.account_time, OutStatus = "新建", Client_name = order.client_name, Warehouse_no = WareCodeLK, Details = order.details.Select(d => new Dt_DeliveryOrderDetail { Goods_no = d.goods_no, Order_qty = LkQty, Batch_num = d.batch_num, Exp_date = d.exp_date, Reservoirarea = WareCodeLK, OotDetailStatus = "新建", Status = 0, }).ToList() }; Repository.AddData(entityOrder); #endregion } } } } catch (Exception e) { content.Error(e.Message); } return content; } #endregion //盘点 拿整个批次信息表的商品批号和商品编号来进行盘点 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 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 != "20").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 != "20" && 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 == "20"); else cabinOrder = Db.Queryable().Includes(x => x.Details).First(x => x.Out_no == orderNo && x.Out_type != "20"); //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 != "20").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")) { materielInfo.Business_qty -= supplyTask.StockQuantity; _basicService.MaterielInfoService.Repository.UpdateData(materielInfo); //if (materielInfo.Business_qty < materielInfo.MinQty) // CreateAllocatInOut(materielInfo);//创建调拨任务 } _unitOfWorkManage.CommitTran(); #endregion content.OK(); } catch (Exception ex) { content.Error(ex.Message); } return content; } } }