yanjinhui
昨天 8cdcf8cb6fecf101bd7dd1db2e44f0cf5ddc0fd4
н¨Îļþ¼Ð/WIDESEA_WMSServer/ClassLibrary2/Inventory_BatchServices.cs.cs
@@ -37,7 +37,7 @@
        /// <summary>
        /// è°ƒæ‹¨å•
        /// è°ƒæ‹¨å• ä¿®æ”¹äº†åº“存信息,以及业务数量
        /// </summary>
        /// <param name="saveModel"></param>
        /// <returns></returns>
@@ -46,26 +46,37 @@
        //    try
        //    {
        //        string WareCode = WarehouseEnum.大件库.ObjToInt().ToString("000");
        //        var qty = saveModel.MainData["availableQuantity"].ObjToInt();
        //        var id = saveModel.MainData["id"].ObjToInt();
        //        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 Inventory_Batch = BaseDal.QueryFirst(x => x.Id == id);
        //        //if (qty > Inventory_Batch.AvailableQuantity) throw new Exception("调拨数量不可大于可用数量");
        //        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_InventoryInfo> 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}】");
        //        var zx = (qty / materielInfo.BoxQty).ObjToInt();
        //        var ys = qty % materielInfo.BoxQty;
        //        if (ys > 0) zx++;
        //        decimal Qty = 0;
        //        // æ£€æŸ¥å¤§ä»¶åº“中是否存在散件
        //        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<Dt_SupplyTask> supplyTasks = new List<Dt_SupplyTask>();
        //        Dt_DeliveryOrder deliveryOrder = new Dt_DeliveryOrder()
        //        {
@@ -75,40 +86,153 @@
        //            OutStatus = "新建",
        //            Details = new List<Dt_DeliveryOrderDetail>()
        //        };
        //        foreach (var item in dt_InventoryInfos)
        //        // æƒ…况1:大件库有散件,且用户输入数量小于等于散件总数,一次性调拨所有散件
        //        if (totalLooseQty > 0 && qty <= totalLooseQty)
        //        {
        //            decimal taskQty = 0;
        //            if (zx < 1) break;
        //            while (item.AvailableQuantity > 0 && zx > 0)
        //            decimal remainingLooseQty = totalLooseQty;
        //            foreach (var item in dt_InventoryInfos)
        //            {
        //                zx--;
        //                Qty += materielInfo.BoxQty;
        //                taskQty += materielInfo.BoxQty;
        //                materielInfo.Business_qty += materielInfo.BoxQty;
        //                item.OutboundQuantity += materielInfo.BoxQty;
        //                item.AvailableQuantity -= materielInfo.BoxQty;
        //                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);
        //                }
        //            }
        //            #region æ·»åŠ è°ƒæ‹¨å‡ºåº“ä»»åŠ¡
        //            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 = taskQty,
        //                SupplyQuantity = 0,
        //                Remark = "调拨出库"
        //            };
        //            supplyTasks.Add(supplyTask);
        //            #endregion
        //        }
        //        // æƒ…况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,
@@ -122,7 +246,8 @@
        //            Reservoirarea = WareCode
        //        };
        //        deliveryOrder.Details.Add(deliveryOrderDetail);
        //        #region æ·»åŠ è°ƒæ‹¨å…¥åº“å•
        //        // æ·»åŠ è°ƒæ‹¨å…¥åº“å•
        //        Dt_CabinOrder cabinOrder = new Dt_CabinOrder()
        //        {
        //            Order_no = deliveryOrder.Out_no,
@@ -144,7 +269,7 @@
        //            };
        //            cabinOrder.Details.Add(orderDetail);
        //        }
        //        #endregion
        //        Db.Ado.BeginTran();
        //        _materielInfoService.UpdateData(materielInfo);
        //        _inventoryInfoService.Repository.UpdateData(dt_InventoryInfos);
@@ -152,7 +277,8 @@
        //        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("调拨出入库单生成成功,请操作调拨单");
        //        return WebResponseContent.Instance.OK($"调拨出入库单生成成功!实际调拨数量:{(int)Qty}");
        //    }
        //    catch (Exception ex)
        //    {
@@ -160,7 +286,6 @@
        //        return WebResponseContent.Instance.Error(ex.Message);
        //    }
        //}
        /// <summary>
@@ -173,8 +298,8 @@
            try
            {
                string WareCode = WarehouseEnum.大件库.ObjToInt().ToString("000");
                var qty = saveModel.MainData["availableQuantity"].ObjToInt();//用户输入的数量
                var id = saveModel.MainData["id"].ObjToInt();//库存批次的id
                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();
@@ -214,7 +339,7 @@
                    Details = new List<Dt_DeliveryOrderDetail>()
                };
                // æƒ…况1:大件库有散件,且用户输入数量小于等于散件总数,一次性调拨所有散件
                // æƒ…况1:大件库有散件,且用户输入数量小于等于散件总数,只调拨所有散件
                if (totalLooseQty > 0 && qty <= totalLooseQty)
                {
                    decimal remainingLooseQty = totalLooseQty;
@@ -247,7 +372,7 @@
                                Creater = App.User.UserName ?? "System",
                                LocationCode = item.LocationCode,
                                OrderNo = deliveryOrder.Out_no,
                                Modifier= item.ValidityPeriod,//效期
                                Modifier = item.ValidityPeriod, // æ•ˆæœŸ
                                StockQuantity = looseQty,
                                SupplyQuantity = 0,
                                Remark = "散件调拨出库(一次性清理)"
@@ -256,102 +381,102 @@
                        }
                    }
                }
                // æƒ…况2:大件库有散件,但用户输入数量大于散件总数,或者大件库没有散件,按原来整箱逻辑
                // æƒ…况2:大件库有散件,但用户输入数量大于散件总数,或者大件库没有散件
                else
                {
                    // å¦‚果大件库有散件但用户要调拨更多,先清理散件
                    decimal allocatedLooseQty = 0;
                    // è®¡ç®—补充的整箱数量
                    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)
                            {
                                // ä¸€æ¬¡æ€§è°ƒæ‹¨è¯¥åº“存记录中的所有散件
                                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);
                                // è°ƒæ‹¨è¯¥åº“存记录中的所有散件
                                decimal transferLooseQty = Math.Min(looseQty, remainingQty);
                                item.OutboundQuantity += transferLooseQty;
                                item.AvailableQuantity -= transferLooseQty;
                                businessQtyToAdd += transferLooseQty;
                                remainingQty -= transferLooseQty;
                            }
                        }
                    }
                    // è®¡ç®—还需要调拨的整箱数量
                    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;
                            if (remainingQty <= 0) break;
                            // è®¡ç®—当前库存可提供的完整箱数
                            var availableFullBoxes = item.AvailableQuantity / materielInfo.BoxQty;
                            var boxesToTransfer = Math.Min(availableFullBoxes, zx);
                            if (boxesToTransfer > 0)
                            // è®¡ç®—当前库存的完整箱数量(已扣除散件)
                            decimal availableFullBoxes = item.AvailableQuantity / materielInfo.BoxQty;
                            if (availableFullBoxes > 0)
                            {
                                var transferQty = boxesToTransfer * materielInfo.BoxQty;
                                taskQty += transferQty;
                                Qty += transferQty;
                                businessQtyToAdd += transferQty;
                                zx -= (int)boxesToTransfer;
                                // è®¡ç®—需要从该库存调拨的箱数
                                decimal boxesToTransfer = Math.Min(availableFullBoxes, remainingQty / materielInfo.BoxQty);
                                decimal transferQty = boxesToTransfer * materielInfo.BoxQty;
                                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);
                                businessQtyToAdd += transferQty;
                                remainingQty -= transferQty;
                            }
                        }
                    }
                        // æ£€æŸ¥æ•´ç®±æ•°é‡æ˜¯å¦è¶³å¤Ÿ
                        if (zx > 0)
                    // æ£€æŸ¥æ˜¯å¦è°ƒæ‹¨å®Œæˆ
                    if (remainingQty > 0)
                    {
                        return WebResponseContent.Instance.Error($"库存不足,无法完成调拨。还需要{remainingQty}个");
                    }
                    // åˆ›å»ºä¸€ä¸ªæ€»ä»»åŠ¡ï¼Œè€Œä¸æ˜¯å¤šä¸ªä»»åŠ¡
                    if (Qty > 0)
                    {
                        // ä½¿ç”¨ç¬¬ä¸€ä¸ªåº“存记录的信息创建任务
                        var firstInventory = dt_InventoryInfos.FirstOrDefault(x => x.OutboundQuantity > 0);
                        if (firstInventory != null)
                        {
                            return WebResponseContent.Instance.Error($"整箱库存不足,无法完成调拨。还需要{zx}ç®±");
                            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);
                        }
                    }
                }
@@ -417,6 +542,282 @@
        /// <summary>
        /// ç§»åº“/将一个库区的库位移到另一个库位
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public WebResponseContent TransferInventory(int[] keys)
        {
            try
            {
                List<Dt_DeliveryOrder> deliveryOrders = new List<Dt_DeliveryOrder>();
                Dt_CabinOrder cabinOrder = null; // åªæœ‰ä¸€ä¸ªå…¥åº“单
                List<Dt_SupplyTask> supplyTasks = new List<Dt_SupplyTask>();
                List<Dt_InventoryInfo> _InventoryInfos = new List<Dt_InventoryInfo>();
                List<Dt_MaterielInfo> materielInfos = new List<Dt_MaterielInfo>();
                List<Dt_Inventory_Batch> batchUpdates=new List<Dt_Inventory_Batch>();
                // å…ˆæ ¹æ®id找到到这个物料以及批次
                var inventory_Batches = BaseDal.QueryData(x => keys.Contains(x.Id)).ToList();
                // æ”¶é›†æ‰€æœ‰æ¶‰åŠçš„库位
                var allWarehouses = new List<string>();
                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>()
                            };
                        }
                        // æ·»åŠ å…¥åº“æ˜Žç»†ï¼ˆæ€»æ•°é‡ï¼‰
                        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<Dt_DeliveryOrderDetail>()
                                };
                            }
                            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);
            }
        }
        /// <summary>
        /// åº“存过期预警
        /// </summary>
        /// <returns></returns>
@@ -430,7 +831,7 @@
                DateTime dateTime180 = DateTime.Now.AddDays(180).Date;
                List<Dt_Inventory_Batch> inventory_Batches = BaseDal.QueryData(x => x.ValidityPeriod < dateTime || x.ValidityPeriod<dateTime60 || x.ValidityPeriod < dateTime180).ToList();
                List<Dt_Inventory_Batch> 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;
@@ -445,5 +846,7 @@
            }
            return content;
        }
    }
}