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(); // 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_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; // 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() // }; // foreach (var item in dt_InventoryInfos) // { // decimal taskQty = 0; // if (zx < 1) break; // while (item.AvailableQuantity > 0 && zx > 0) // { // zx--; // Qty += materielInfo.BoxQty; // taskQty += materielInfo.BoxQty; // materielInfo.Business_qty += materielInfo.BoxQty; // item.OutboundQuantity += materielInfo.BoxQty; // item.AvailableQuantity -= materielInfo.BoxQty; // } // #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 // } // 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); // #region 添加调拨入库单 // 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); // } // #endregion // 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("调拨出入库单生成成功,请操作调拨单"); // } // 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 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 WebResponseContent GetExpiredAndlow() { WebResponseContent content = new WebResponseContent(); try { DateTime dateTime = DateTime.Now.AddDays(30).Date; List inventory_Batches = BaseDal.QueryData(x => x.ValidityPeriod < dateTime); 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; } } }