using SqlSugar.Extensions; using System; using System.Collections.Generic; using System.Drawing.Drawing2D; using System.Linq; using System.Text; using System.Threading.Tasks; 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_IWMsInfoServices; using WIDESEA_Model.Models; namespace WIDESEA_WMsInfoServices { public class Inventory_BatchServices : ServiceBase>, IInventory_BatchServices { private IMessageInfoService _messageInfoService; private IMaterielInfoService _materielInfoService; private IInventoryInfoService _inventoryInfoService; private ISupplyTaskService _supplyTaskService; public Inventory_BatchServices(IRepository BaseDal, IMessageInfoService messageInfoService, IMaterielInfoService materielInfoService, IInventoryInfoService inventoryInfoService, ISupplyTaskService supplyTaskService) : base(BaseDal) { _messageInfoService = messageInfoService; _materielInfoService = materielInfoService; _inventoryInfoService = inventoryInfoService; _supplyTaskService = supplyTaskService; } public IRepository Repository => BaseDal; /// /// 调拨单 修改了库存信息,以及业务数量 /// /// /// //public override WebResponseContent UpdateData(SaveModel saveModel) //{ // try // { // string WareCode = WarehouseEnum.大件库.ObjToInt().ToString("000"); // var qty = saveModel.MainData["availableQuantity"].ObjToInt();//用户输入的数量 // var id = saveModel.MainData["id"].ObjToInt();//库存批次的id // var materielCode = saveModel.MainData["materielCode"].ToString(); // var batchNo = saveModel.MainData["batchNo"].ToString(); // var materielInfo = _materielInfoService.Repository.QueryFirst(x => x.MaterielCode == materielCode); // if (materielInfo == null) return WebResponseContent.Instance.Error($"请维护药品编号【{materielCode}】的信息"); // if (!Enum.IsDefined(typeof(MaterielSourceTypeEnum), materielInfo.MaterielSourceType)) // return WebResponseContent.Instance.Error($"请设置药品编号【{materielCode}】的属性分类"); // if (materielInfo.MaterielSourceType == MaterielSourceTypeEnum.PurchasePart) // return WebResponseContent.Instance.Error($"药品编号【{materielCode}】的属性分类为大件,不可调拨"); // List dt_InventoryInfos = _inventoryInfoService.Repository.QueryData(x => x.MaterielCode == materielInfo.MaterielCode && x.BatchNo == batchNo && x.StockStatus == StockStatusEmun.入库完成.ObjToInt() && x.AvailableQuantity > 0 && x.WarehouseCode == WareCode).OrderBy(x => x.InDate).ToList(); // if (dt_InventoryInfos.Count < 1) return WebResponseContent.Instance.Error($"物料编号【{materielInfo.MaterielCode}】大件库无库存!请及时补充库存!"); // var StockQty = dt_InventoryInfos.Sum(x => x.AvailableQuantity); // if (StockQty < qty) return WebResponseContent.Instance.Error($"调拨数量不可大于大件库可用数量,大件库可用数量为【{StockQty}】"); // // 检查大件库中是否存在散件 // decimal totalLooseQty = 0; // foreach (var inventory in dt_InventoryInfos) // { // var looseQty = inventory.AvailableQuantity % materielInfo.BoxQty; // if (looseQty > 0) // { // totalLooseQty += looseQty; // } // } // decimal Qty = 0; // 实际调拨总数量 // decimal businessQtyToAdd = 0; // 需要添加到业务数量的数量 // List supplyTasks = new List(); // Dt_DeliveryOrder deliveryOrder = new Dt_DeliveryOrder() // { // Out_no = DateTime.Now.ToString("yyMMddHHmmss"), // Warehouse_no = WareCode, // Out_type = OutOrderTypeEnum.Allocate.ObjToInt().ToString(), // OutStatus = "新建", // Details = new List() // }; // // 情况1:大件库有散件,且用户输入数量小于等于散件总数,一次性调拨所有散件 // if (totalLooseQty > 0 && qty <= totalLooseQty) // { // decimal remainingLooseQty = totalLooseQty; // foreach (var item in dt_InventoryInfos) // { // if (remainingLooseQty <= 0) break; // var looseQty = item.AvailableQuantity % materielInfo.BoxQty; // if (looseQty > 0) // { // // 一次性调拨该库存记录中的所有散件 // item.OutboundQuantity += looseQty; // item.AvailableQuantity -= looseQty; // Qty += looseQty; // businessQtyToAdd += looseQty; // remainingLooseQty -= looseQty; // // 添加供应任务 // 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 = TaskTypeEnum.AllocatOut.ObjToInt(), // CreateDate = DateTime.Now, // Creater = App.User.UserName ?? "System", // LocationCode = item.LocationCode, // OrderNo = deliveryOrder.Out_no, // Modifier = item.ValidityPeriod,//效期 // StockQuantity = looseQty, // SupplyQuantity = 0, // Remark = "散件调拨出库(一次性清理)" // }; // supplyTasks.Add(supplyTask); // } // } // } // // 情况2:大件库有散件,但用户输入数量大于散件总数,或者大件库没有散件,按原来整箱逻辑 // else // { // // 如果大件库有散件但用户要调拨更多,先清理散件 // decimal allocatedLooseQty = 0; // if (totalLooseQty > 0) // { // foreach (var item in dt_InventoryInfos) // { // var looseQty = item.AvailableQuantity % materielInfo.BoxQty; // if (looseQty > 0) // { // // 一次性调拨该库存记录中的所有散件 // item.OutboundQuantity += looseQty; // item.AvailableQuantity -= looseQty; // allocatedLooseQty += looseQty; // Qty += looseQty; // businessQtyToAdd += looseQty; // // 添加供应任务 // 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 = TaskTypeEnum.AllocatOut.ObjToInt(), // CreateDate = DateTime.Now, // Creater = App.User.UserName ?? "System", // LocationCode = item.LocationCode, // OrderNo = deliveryOrder.Out_no, // StockQuantity = looseQty, // Modifier = item.ValidityPeriod,//效期 // SupplyQuantity = 0, // Remark = "散件调拨出库(一次性清理)" // }; // supplyTasks.Add(supplyTask); // } // } // } // // 计算还需要调拨的整箱数量 // var remainingQty = qty - allocatedLooseQty; // if (remainingQty > 0) // { // var zx = (int)Math.Ceiling((decimal)remainingQty / materielInfo.BoxQty); // 需要的整箱数 // foreach (var item in dt_InventoryInfos) // { // decimal taskQty = 0; // if (zx < 1) break; // // 计算当前库存可提供的完整箱数 // var availableFullBoxes = item.AvailableQuantity / materielInfo.BoxQty; // var boxesToTransfer = Math.Min(availableFullBoxes, zx); // if (boxesToTransfer > 0) // { // var transferQty = boxesToTransfer * materielInfo.BoxQty; // taskQty += transferQty; // Qty += transferQty; // businessQtyToAdd += transferQty; // zx -= (int)boxesToTransfer; // item.OutboundQuantity += transferQty; // item.AvailableQuantity -= transferQty; // // 添加供应任务 // 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 = TaskTypeEnum.AllocatOut.ObjToInt(), // CreateDate = DateTime.Now, // Creater = App.User.UserName ?? "System", // LocationCode = item.LocationCode, // OrderNo = deliveryOrder.Out_no, // Modifier = item.ValidityPeriod,//效期 // StockQuantity = taskQty, // SupplyQuantity = 0, // Remark = "整箱调拨出库" // }; // supplyTasks.Add(supplyTask); // } // } // // 检查整箱数量是否足够 // if (zx > 0) // { // return WebResponseContent.Instance.Error($"整箱库存不足,无法完成调拨。还需要{zx}箱"); // } // } // } // // 更新业务数量:业务数量 = 原来的业务数量 + 实际调拨总数量 // materielInfo.Business_qty += businessQtyToAdd; // // 添加出库单明细 // Dt_DeliveryOrderDetail deliveryOrderDetail = new Dt_DeliveryOrderDetail() // { // Batch_num = batchNo, // Order_Outqty = 0, // Order_qty = Qty, // CreateDate = DateTime.Now, // Creater = App.User.UserName ?? "System", // Goods_no = materielCode, // OotDetailStatus = "新建", // Status = 2, // Reservoirarea = WareCode // }; // deliveryOrder.Details.Add(deliveryOrderDetail); // // 添加调拨入库单 // Dt_CabinOrder cabinOrder = new Dt_CabinOrder() // { // Order_no = deliveryOrder.Out_no, // Order_type = InOrderTypeEnum.Allocat.ObjToInt().ToString(), // Warehouse_no = "001", // OdrderStatus = "新建", // Details = new List() // }; // foreach (var item in deliveryOrder.Details) // { // Dt_CabinOrderDetail orderDetail = new Dt_CabinOrderDetail() // { // Reservoirarea = cabinOrder.Warehouse_no, // Goods_no = item.Goods_no, // Order_qty = item.Order_qty, // Batch_num = item.Batch_num, // OrderDetailStatus = "新建", // Status = 0 // }; // cabinOrder.Details.Add(orderDetail); // } // Db.Ado.BeginTran(); // _materielInfoService.UpdateData(materielInfo); // _inventoryInfoService.Repository.UpdateData(dt_InventoryInfos); // _supplyTaskService.AddData(supplyTasks); // if (deliveryOrder.Details.Count > 0) Db.InsertNav(deliveryOrder).Include(x => x.Details).ExecuteCommand(); // if (cabinOrder.Details.Count > 0) Db.InsertNav(cabinOrder).Include(x => x.Details).ExecuteCommand(); // Db.Ado.CommitTran(); // return WebResponseContent.Instance.OK($"调拨出入库单生成成功!实际调拨数量:{(int)Qty}"); // } // catch (Exception ex) // { // Db.Ado.RollbackTran(); // return WebResponseContent.Instance.Error(ex.Message); // } //} /// /// 调拨单 /// /// /// public override WebResponseContent UpdateData(SaveModel saveModel) { try { string WareCode = WarehouseEnum.大件库.ObjToInt().ToString("000"); var qty = saveModel.MainData["availableQuantity"].ObjToInt(); // 用户输入的数量 var id = saveModel.MainData["id"].ObjToInt(); // 库存批次的id var materielCode = saveModel.MainData["materielCode"].ToString(); var batchNo = saveModel.MainData["batchNo"].ToString(); var materielInfo = _materielInfoService.Repository.QueryFirst(x => x.MaterielCode == materielCode); if (materielInfo == null) return WebResponseContent.Instance.Error($"请维护药品编号【{materielCode}】的信息"); if (!Enum.IsDefined(typeof(MaterielSourceTypeEnum), materielInfo.MaterielSourceType)) return WebResponseContent.Instance.Error($"请设置药品编号【{materielCode}】的属性分类"); if (materielInfo.MaterielSourceType == MaterielSourceTypeEnum.PurchasePart) return WebResponseContent.Instance.Error($"药品编号【{materielCode}】的属性分类为大件,不可调拨"); List dt_InventoryInfos = _inventoryInfoService.Repository.QueryData(x => x.MaterielCode == materielInfo.MaterielCode && x.BatchNo == batchNo && x.StockStatus == StockStatusEmun.入库完成.ObjToInt() && x.AvailableQuantity > 0 && x.WarehouseCode == WareCode).OrderBy(x => x.InDate).ToList(); if (dt_InventoryInfos.Count < 1) return WebResponseContent.Instance.Error($"物料编号【{materielInfo.MaterielCode}】大件库无库存!请及时补充库存!"); var StockQty = dt_InventoryInfos.Sum(x => x.AvailableQuantity); if (StockQty < qty) return WebResponseContent.Instance.Error($"调拨数量不可大于大件库可用数量,大件库可用数量为【{StockQty}】"); // 检查大件库中是否存在散件 decimal totalLooseQty = 0; foreach (var inventory in dt_InventoryInfos) { var looseQty = inventory.AvailableQuantity % materielInfo.BoxQty; if (looseQty > 0) { totalLooseQty += looseQty; } } decimal Qty = 0; // 实际调拨总数量 decimal businessQtyToAdd = 0; // 需要添加到业务数量的数量 List supplyTasks = new List(); Dt_DeliveryOrder deliveryOrder = new Dt_DeliveryOrder() { Out_no = DateTime.Now.ToString("yyMMddHHmmss"), Warehouse_no = WareCode, Out_type = OutOrderTypeEnum.Allocate.ObjToInt().ToString(), OutStatus = "新建", Details = new List() }; // 情况1:大件库有散件,且用户输入数量小于等于散件总数,只调拨所有散件 if (totalLooseQty > 0 && qty <= totalLooseQty) { decimal remainingLooseQty = totalLooseQty; foreach (var item in dt_InventoryInfos) { if (remainingLooseQty <= 0) break; var looseQty = item.AvailableQuantity % materielInfo.BoxQty; if (looseQty > 0) { // 一次性调拨该库存记录中的所有散件 item.OutboundQuantity += looseQty; item.AvailableQuantity -= looseQty; Qty += looseQty; businessQtyToAdd += looseQty; remainingLooseQty -= looseQty; // 添加供应任务 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 = TaskTypeEnum.AllocatOut.ObjToInt(), CreateDate = DateTime.Now, Creater = App.User.UserName ?? "System", LocationCode = item.LocationCode, OrderNo = deliveryOrder.Out_no, Modifier = item.ValidityPeriod, // 效期 StockQuantity = looseQty, SupplyQuantity = 0, Remark = "散件调拨出库(一次性清理)" }; supplyTasks.Add(supplyTask); } } } // 情况2:大件库有散件,但用户输入数量大于散件总数,或者大件库没有散件 else { // 计算补充的整箱数量 decimal remainingAfterLoose = qty - totalLooseQty; decimal additionalBoxesNeeded = 0; if (remainingAfterLoose > 0) { // 向上取整计算需要的额外整箱数 additionalBoxesNeeded = Math.Ceiling(remainingAfterLoose / materielInfo.BoxQty); //向上取整: } // 总调拨量 = 所有散件 + 补充的整箱 Qty = totalLooseQty + (additionalBoxesNeeded * materielInfo.BoxQty); // 开始实际调拨 decimal remainingQty = Qty; // 先调拨所有散件 if (totalLooseQty > 0) { foreach (var item in dt_InventoryInfos) { if (remainingQty <= 0) break; var looseQty = item.AvailableQuantity % materielInfo.BoxQty; if (looseQty > 0) { // 调拨该库存记录中的所有散件 decimal transferLooseQty = Math.Min(looseQty, remainingQty); item.OutboundQuantity += transferLooseQty; item.AvailableQuantity -= transferLooseQty; businessQtyToAdd += transferLooseQty; remainingQty -= transferLooseQty; } } } // 如果还有剩余需要调拨的数量(补充的整箱),从整箱中调拨 if (remainingQty > 0) { foreach (var item in dt_InventoryInfos) { if (remainingQty <= 0) break; // 计算当前库存的完整箱数量(已扣除散件) decimal availableFullBoxes = item.AvailableQuantity / materielInfo.BoxQty; if (availableFullBoxes > 0) { // 计算需要从该库存调拨的箱数 decimal boxesToTransfer = Math.Min(availableFullBoxes, remainingQty / materielInfo.BoxQty); decimal transferQty = boxesToTransfer * materielInfo.BoxQty; item.OutboundQuantity += transferQty; item.AvailableQuantity -= transferQty; businessQtyToAdd += transferQty; remainingQty -= transferQty; } } } // 检查是否调拨完成 if (remainingQty > 0) { return WebResponseContent.Instance.Error($"库存不足,无法完成调拨。还需要{remainingQty}个"); } // 创建一个总任务,而不是多个任务 if (Qty > 0) { // 使用第一个库存记录的信息创建任务 var firstInventory = dt_InventoryInfos.FirstOrDefault(x => x.OutboundQuantity > 0); if (firstInventory != null) { Dt_SupplyTask supplyTask = new Dt_SupplyTask() { WarehouseCode = firstInventory.WarehouseCode, BatchNo = firstInventory.BatchNo, MaterielName = firstInventory.MaterielName, MaterielCode = firstInventory.MaterielCode, MaterielSpec = firstInventory.MaterielSpec, TaskStatus = SupplyStatusEnum.NewOut.ObjToInt(), TaskType = TaskTypeEnum.AllocatOut.ObjToInt(), CreateDate = DateTime.Now, Creater = App.User.UserName ?? "System", LocationCode = firstInventory.LocationCode, OrderNo = deliveryOrder.Out_no, Modifier = firstInventory.ValidityPeriod, // 效期 StockQuantity = Qty, // 总调拨数量 SupplyQuantity = 0, Remark = additionalBoxesNeeded > 0 ? $"调拨出库 {Qty}个(散件{totalLooseQty}个 + 整箱{additionalBoxesNeeded}箱,用户需求{qty}个)" : $"调拨出库 {Qty}个(散件,用户需求{qty}个)" }; supplyTasks.Add(supplyTask); } } } // 更新业务数量:业务数量 = 原来的业务数量 + 实际调拨总数量 materielInfo.Business_qty += businessQtyToAdd; // 添加出库单明细 Dt_DeliveryOrderDetail deliveryOrderDetail = new Dt_DeliveryOrderDetail() { Batch_num = batchNo, Order_Outqty = 0, Order_qty = Qty, CreateDate = DateTime.Now, Creater = App.User.UserName ?? "System", Goods_no = materielCode, OotDetailStatus = "新建", Status = 2, Reservoirarea = WareCode }; deliveryOrder.Details.Add(deliveryOrderDetail); // 添加调拨入库单 Dt_CabinOrder cabinOrder = new Dt_CabinOrder() { Order_no = deliveryOrder.Out_no, Order_type = InOrderTypeEnum.Allocat.ObjToInt().ToString(), Warehouse_no = "001", OdrderStatus = "新建", Details = new List() }; foreach (var item in deliveryOrder.Details) { Dt_CabinOrderDetail orderDetail = new Dt_CabinOrderDetail() { Reservoirarea = cabinOrder.Warehouse_no, Goods_no = item.Goods_no, Order_qty = item.Order_qty, Batch_num = item.Batch_num, OrderDetailStatus = "新建", Status = 0 }; cabinOrder.Details.Add(orderDetail); } Db.Ado.BeginTran(); _materielInfoService.UpdateData(materielInfo); _inventoryInfoService.Repository.UpdateData(dt_InventoryInfos); _supplyTaskService.AddData(supplyTasks); if (deliveryOrder.Details.Count > 0) Db.InsertNav(deliveryOrder).Include(x => x.Details).ExecuteCommand(); if (cabinOrder.Details.Count > 0) Db.InsertNav(cabinOrder).Include(x => x.Details).ExecuteCommand(); Db.Ado.CommitTran(); return WebResponseContent.Instance.OK($"调拨出入库单生成成功!实际调拨数量:{(int)Qty}"); } catch (Exception ex) { Db.Ado.RollbackTran(); return WebResponseContent.Instance.Error(ex.Message); } } /// /// 移库/将一个库区的库位移到另一个库位 /// /// /// public WebResponseContent TransferInventory(int[] keys) { try { List deliveryOrders = new List(); Dt_CabinOrder cabinOrder = null; // 只有一个入库单 List supplyTasks = new List(); List _InventoryInfos = new List(); List materielInfos = new List(); List batchUpdates=new List(); // 先根据id找到到这个物料以及批次 var inventory_Batches = BaseDal.QueryData(x => keys.Contains(x.Id)).ToList(); // 收集所有涉及的库位 var allWarehouses = new List(); foreach (var item in inventory_Batches) { var inventoryInfos = _inventoryInfoService.Repository.QueryData(x => x.MaterielCode == item.MaterielCode && x.BatchNo == item.BatchNo).ToList(); if (inventoryInfos.Count > 0) { allWarehouses.AddRange(inventoryInfos.Select(x => x.WarehouseCode)); } } var distinctWarehouses = allWarehouses.Distinct().ToList(); // 确定移位类型和目标库位 bool has001 = distinctWarehouses.Contains("001"); bool has002 = distinctWarehouses.Contains("002"); bool has003 = distinctWarehouses.Contains("003"); bool has010 = distinctWarehouses.Contains("010"); string targetWarehouseCode; bool isSameWarehouseShift = false; #region 规则 // 规则1:如果同时存在001和002,全部移到002 if (has001 && has002) { targetWarehouseCode = "002"; } // 规则2:如果只有001,移到002 else if (has001 && !has002) { targetWarehouseCode = "002"; } // 规则3:如果只有002,在002内移位 else if (has002 && !has001) { targetWarehouseCode = "002"; isSameWarehouseShift = true; } // 规则4:如果只有003,在003内移位 else if (has003 && distinctWarehouses.Count == 1) { targetWarehouseCode = "003"; isSameWarehouseShift = true; } // 规则5:如果只有010,在010内移位 else if (has010 && distinctWarehouses.Count == 1) { targetWarehouseCode = "010"; isSameWarehouseShift = true; } else { throw new Exception("无效的库存组合或跨库房移位不允许"); } #endregion // 先判断这个是否有待出库数量,以及盘点差异数 foreach (var item in inventory_Batches) { #region 判断是否创建 var supplyTask1 = _supplyTaskService.Repository.QueryData(x => x.MaterielCode == item.MaterielCode && x.BatchNo == item.BatchNo && x.TaskType == TaskTypeEnum.TransferOut.ObjToInt()).ToList(); if (supplyTask1.Count>0) throw new Exception($"物料编号【{item.MaterielCode}】批次号【{item.BatchNo}】已存在移库任务,请先完成当前移库任务"); // 查找任务中是否存在待盘点任务 supplyTask1 = _supplyTaskService.Repository.QueryData(x => x.MaterielCode == item.MaterielCode && x.BatchNo == item.BatchNo && x.TaskStatus == SupplyStatusEnum.NewCheck.ObjToInt()).ToList(); if (supplyTask1.Count > 0) throw new Exception($"物料编号【{item.MaterielCode}】批次号【{item.BatchNo}】已存在盘点任务,请先完成当前盘点任务"); // 查找任务中是否存在出库任务 supplyTask1 = _supplyTaskService.Repository.QueryData(x => x.MaterielCode == item.MaterielCode && x.BatchNo == item.BatchNo && x.TaskStatus == SupplyStatusEnum.NewOut.ObjToInt()).ToList(); if (supplyTask1.Count > 0) throw new Exception($"物料编号【{item.MaterielCode}】批次号【{item.BatchNo}】已存在出库任务,请先完成当前出库任务"); #endregion // 查找库存信息 var inventoryInfos = _inventoryInfoService.Repository.QueryData(x => x.MaterielCode == item.MaterielCode && x.BatchNo == item.BatchNo).ToList(); if (inventoryInfos.Count > 0) { // 计算该物料批次的总库存数量(所有库位) decimal totalStockQuantity = inventoryInfos.Sum(x => x.StockQuantity); // 直接更新批次对象的字段 item.OutboundQuantity += totalStockQuantity; item.AvailableQuantity -= totalStockQuantity; // 添加到更新列表(如果还没添加过) if (!batchUpdates.Any(x => x.Id == item.Id)) { batchUpdates.Add(item); } // 创建入库单(只有一个) if (cabinOrder == null) { cabinOrder = new Dt_CabinOrder() { Order_no = $"RK{targetWarehouseCode}{DateTime.Now.ToString("yyMMddHHmmss")}", Order_type = "40", // 移位入库 OdrderStatus = "新建", Warehouse_no = targetWarehouseCode, Details = new List() }; } // 添加入库明细(总数量) Dt_CabinOrderDetail cabinOrderDetail = new Dt_CabinOrderDetail() { Batch_num = item.BatchNo, Order_Inqty = 0, Order_qty = totalStockQuantity, // 所有库位的总数量 CreateDate = DateTime.Now, Creater = App.User.UserName, Goods_no = item.MaterielCode, OrderDetailStatus = "新建", Status = targetWarehouseCode == "001" ? 0 : 2, Reservoirarea = targetWarehouseCode, }; // 检查是否已有相同物料批次的入库明细 var existingDetail = cabinOrder.Details.FirstOrDefault(x => x.Goods_no == item.MaterielCode && x.Batch_num == item.BatchNo); if (existingDetail != null) { // 如果已存在,合并数量 existingDetail.Order_qty += totalStockQuantity; } else { // 添加入库 cabinOrder.Details.Add(cabinOrderDetail); } // 根据库房号来进行分组,为每个源库位创建出库单 foreach (var items in inventoryInfos.GroupBy(x => x.WarehouseCode)) { string sourceWarehouseCode = items.Key; //// 如果是同库房移位且源库位就是目标库位,跳过(不移到自身) //if (isSameWarehouseShift && sourceWarehouseCode == targetWarehouseCode) // continue; // 查找到该库房号的出库单 var deliveryOrder = deliveryOrders.Where(x => x.Warehouse_no == sourceWarehouseCode).FirstOrDefault(); bool isNull = false; if (deliveryOrder == null) { isNull = true; deliveryOrder = new Dt_DeliveryOrder() { Out_no = $"YK{sourceWarehouseCode}{DateTime.Now.ToString("yyMMddHHmmss")}{new Random().Next(1000, 9999)}", Out_type = "30", // 移位出库 OutStatus = "新建", Warehouse_no = sourceWarehouseCode, Details = new List() }; } var Status = sourceWarehouseCode == "001" ? 0 : 2; // 判断是否为立库区域 Dt_DeliveryOrderDetail deliveryOrderDetail = new Dt_DeliveryOrderDetail() { Batch_num = item.BatchNo, Order_Outqty = 0, Order_qty = items.Select(x => x.StockQuantity).Sum(), // 该库位的数量 CreateDate = DateTime.Now, Creater = App.User.UserName, Goods_no = item.MaterielCode, OotDetailStatus = "新建", Status = Status, Reservoirarea = sourceWarehouseCode, }; deliveryOrder.Details.Add(deliveryOrderDetail); if (isNull) deliveryOrders.Add(deliveryOrder); #region 创建移库出库任务 foreach (var inventory in items) { // 保存原来的库存数量 decimal originalStockQuantity = inventory.StockQuantity; // 更新库存信息:增加待出库数量,减少可用库存 inventory.OutboundQuantity += originalStockQuantity; inventory.AvailableQuantity -= originalStockQuantity; Dt_SupplyTask supplyTask = new Dt_SupplyTask() { WarehouseCode = inventory.WarehouseCode, TaskStatus = SupplyStatusEnum.NewOut.ObjToInt(), BatchNo = inventory.BatchNo, MaterielName = inventory.MaterielName, MaterielCode = inventory.MaterielCode, MaterielSpec = inventory.MaterielSpec, TaskType = TaskTypeEnum.TransferOut.ObjToInt(), CreateDate = DateTime.Now, Creater = App.User.UserName, LocationCode = inventory.LocationCode, OrderNo = deliveryOrder.Out_no, StockQuantity = inventory.StockQuantity, Modifier = inventory.ValidityPeriod, // 效期 SupplyQuantity = 0, Remark = isSameWarehouseShift ? $"在{sourceWarehouseCode}库房内移位" : $"从{sourceWarehouseCode}移库到{targetWarehouseCode}", }; supplyTasks.Add(supplyTask); _InventoryInfos.Add(inventory); } #endregion } } } // 检查是否有需要移位的库存 if (cabinOrder == null || cabinOrder.Details.Count == 0) throw new Exception("没有需要移位的库存"); _InventoryInfos.ForEach(x => { x.StockStatus = StockStatusEmun.移位中.ObjToInt(); }); Db.Ado.BeginTran(); _materielInfoService.UpdateData(materielInfos); _inventoryInfoService.UpdateData(_InventoryInfos); _supplyTaskService.AddData(supplyTasks); BaseDal.UpdateData(batchUpdates); // 批量插入出库单(每个源库位一个) foreach (var deliveryOrder in deliveryOrders) { if (deliveryOrder.Details.Count > 0) Db.InsertNav(deliveryOrder).Include(x => x.Details).ExecuteCommand(); } // 插入入库单(只有一个) if (cabinOrder != null && cabinOrder.Details.Count > 0) Db.InsertNav(cabinOrder).Include(x => x.Details).ExecuteCommand(); Db.Ado.CommitTran(); string message = isSameWarehouseShift ? "库内货位调整单生成成功!" : "移库出入库单生成成功!"; return WebResponseContent.Instance.OK(message); } catch (Exception ex) { Db.Ado.RollbackTran(); return WebResponseContent.Instance.Error(ex.Message); } } /// /// 库存过期预警 /// /// public WebResponseContent GetExpiredAndlow() { WebResponseContent content = new WebResponseContent(); try { DateTime dateTime = DateTime.Now.AddDays(30).Date; DateTime dateTime60 = DateTime.Now.AddDays(60).Date; DateTime dateTime180 = DateTime.Now.AddDays(180).Date; List inventory_Batches = BaseDal.QueryData(x => x.ValidityPeriod < dateTime || x.ValidityPeriod < dateTime60 || x.ValidityPeriod < dateTime180).ToList(); foreach (var item in inventory_Batches) { var day = (item.ValidityPeriod - DateTime.Now).Days; string d = $"还有{day}天过期"; if (day < 0) d = $"已过期{Math.Abs(day)}天"; _messageInfoService.AddMessageInfo(MessageGroupByEnum.InventoryExceedAlarm, "物料名称:" + item.MaterielName, $"物料编号【{item.MaterielCode}】物料批次【{item.BatchNo}】{d}", messageRemark: $"物料编号【{item.MaterielCode}】物料批次【{item.BatchNo}】"); } } catch (Exception ex) { content.Error(ex.Message); } return content; } } }