| using System; | 
| using System.Collections.Generic; | 
| using System.Linq; | 
| using System.Text; | 
| using System.Threading.Tasks; | 
| using WIDESEA_Common.StockEnum; | 
| using WIDESEA_Common.WareHouseEnum; | 
| using WIDESEA_Core; | 
| using WIDESEA_Core.BaseServices; | 
| using WIDESEA_Core.Enums; | 
| using WIDESEA_Core.Helper; | 
| using WIDESEA_IBasicRepository; | 
| using WIDESEA_IStockRepository; | 
| using WIDESEA_IStockService; | 
| using WIDESEA_Model.Models; | 
|   | 
| namespace WIDESEA_StockService | 
| { | 
|     public partial class ProStockInfoService : ServiceBase<Dt_ProStockInfo, IProStockInfoRepository>, IProStockInfoService | 
|     { | 
|         public IProStockInfoRepository Repository => BaseDal; | 
|         private readonly IStockRepository _stockRepository; | 
|         private readonly IBasicRepository _basicRepository; | 
|         public ProStockInfoService(IProStockInfoRepository BaseDal,IStockRepository stockRepository, IBasicRepository basicRepository) : base(BaseDal) | 
|         { | 
|             _stockRepository = stockRepository; | 
|             _basicRepository = basicRepository; | 
|         } | 
|         /// <summary> | 
|         /// 根据外包信息解绑内包信息 | 
|         /// </summary> | 
|         public WebResponseContent UnBindStock(List<Dt_ProStockInfoDetail> proStockInfoDetails) | 
|         { | 
|             WebResponseContent content = new WebResponseContent(); | 
|             //根据内包号进行库存扣除 | 
|             try | 
|             { | 
|                 //获取库存 | 
|                 List<string> BagNos = proStockInfoDetails.Select(x => x.BagNo).Distinct().ToList(); | 
|                 List<Dt_ProStockInfo> proStockInfos = _stockRepository.ProStockInfoRepository.Db.Queryable<Dt_ProStockInfo>() | 
|                     .Where(x => x.StockStatus == StockStatusEmun.出库完成.ObjToInt()) | 
|                     .Includes(x => x.proStockInfoDetails) | 
|                     .Where(x => x.proStockInfoDetails.Any(v => BagNos.Contains(v.BagNo))).Distinct().ToList(); | 
|                 List<Dt_ProStockInfoDetail> delProStockDetails=new List<Dt_ProStockInfoDetail>(); | 
|                 List<Dt_ProStockInfoDetail> upProStockDetails = new List<Dt_ProStockInfoDetail>(); | 
|                 List<Dt_ProStockInfo> delProStockInfos = new List<Dt_ProStockInfo>(); | 
|                 foreach (var item in proStockInfoDetails) | 
|                 { | 
|                     Dt_ProStockInfo? proStockInfo = proStockInfos.Where(x => x.proStockInfoDetails.Any(v => v.BagNo == item?.BagNo)).FirstOrDefault(); | 
|                     Dt_ProStockInfoDetail? proStockInfoDetail = proStockInfo?.proStockInfoDetails.Where(x => x.BagNo == item?.BagNo).FirstOrDefault(); | 
|                     if (proStockInfo==null || proStockInfoDetail == null) | 
|                     { | 
|                        return content.Error($"未找到{item?.BagNo}库存"); | 
|                     } | 
|                      | 
|                     //判断明细是否全部扫出 | 
|                     if (proStockInfoDetail.StockPcsQty==item.StockPcsQty) | 
|                     { | 
|                         delProStockDetails.Add(proStockInfoDetail); | 
|                         proStockInfo.proStockInfoDetails.Remove(proStockInfoDetail); | 
|                         item.OutDetailId = proStockInfoDetail.OutDetailId; | 
|                         item.OutDetailSaleNo = proStockInfoDetail.OutDetailSaleNo; | 
|                     } | 
|                     else | 
|                     { | 
|                         proStockInfoDetail.StockPcsQty -= item.StockPcsQty; | 
|                         proStockInfoDetail.SETQty -= item.SETQty; | 
|                         proStockInfoDetail.OutboundQuantity = 0; | 
|                         item.OutDetailId = 0; | 
|                         item.OutDetailSaleNo = ""; | 
|                         upProStockDetails.Add(proStockInfoDetail); | 
|                     } | 
|   | 
|                     if (proStockInfo.proStockInfoDetails.Count==0) | 
|                     { | 
|                         delProStockInfos.Add(proStockInfo); | 
|                     } | 
|                 } | 
|                 if (delProStockInfos.Count>0) | 
|                 { | 
|                     BaseDal.DeleteAndMoveIntoHty(delProStockInfos, OperateTypeEnum.自动删除); | 
|                 } | 
|                 if (delProStockDetails.Count > 0) | 
|                 { | 
|                     _stockRepository.ProStockInfoDetailRepository.DeleteAndMoveIntoHty(delProStockDetails, OperateTypeEnum.自动删除); | 
|                 } | 
|                 if (upProStockDetails.Count > 0) | 
|                 { | 
|                     _stockRepository.ProStockInfoDetailRepository.UpdateData(upProStockDetails); | 
|                 } | 
|                 content.OK("成功", proStockInfoDetails); | 
|             } | 
|             catch (Exception ex) | 
|             { | 
|                 content.Error(ex.Message); | 
|             } | 
|             return content; | 
|         } | 
|         //查找可用库存 | 
|         public List<Dt_ProStockInfo> GetUseableStocks(int warehoseId,Dt_ProOutOrderDetail proOutOrderDetail) | 
|         { | 
|             List<string> locationCodes = _basicRepository.LocationInfoRepository.GetCanOutLocationCodes(warehoseId); | 
|             return BaseDal.GetProStocks(proOutOrderDetail,locationCodes); | 
|         } | 
|         /// <summary> | 
|         /// MES提库可用库存 | 
|         /// </summary> | 
|         /// <returns></returns> | 
|         public List<Dt_ProStockInfo> GetUseableStocks(Dt_MesRworkOutboundOrder mesRworkOutboundOrder) | 
|         { | 
|             //转换成 成品仓仓库信息获取尾数属性的货位 | 
|             Dt_Warehouse warehouse = _basicRepository.WarehouseRepository.QueryFirst(x=>x.WarehouseId== mesRworkOutboundOrder.WarehouseId); | 
|             List<string> locationCodes = _basicRepository.LocationInfoRepository.GetCanOutLocationCodes(warehouse.WarehouseId); | 
|             return BaseDal.GetProStocks(mesRworkOutboundOrder, locationCodes); | 
|         } | 
|         //查找可用报废库存 | 
|         public List<Dt_ProStockInfo> GetUseableStocks(int warehoseId, Dt_ErpProScrapSheetDetail erpProScrapSheetDetail) | 
|         { | 
|             List<string> locationCodes = _basicRepository.LocationInfoRepository.GetCanOutLocationCodes(warehoseId); | 
|             return BaseDal.GetProStocks(erpProScrapSheetDetail, locationCodes); | 
|         } | 
|         /// <summary> | 
|         /// 获取出库库存 | 
|         /// </summary> | 
|         public List<Dt_ProStockInfo> GetOutboundStocks(List<Dt_ProStockInfo> stockInfos, Dt_ProOutOrderDetail outOrderDetail, float needQuantity, out float residueQuantity) | 
|         { | 
|             List<Dt_ProStockInfo> assignOutStocks =new List<Dt_ProStockInfo>(); | 
|             bool isCanLot = string.IsNullOrEmpty(outOrderDetail.PLot); | 
|             bool isCanDate = string.IsNullOrEmpty(outOrderDetail.DateCode); | 
|             float stockTotalQuantity = stockInfos.Select(x => x.proStockInfoDetails.Where(x => x.ProductCode == outOrderDetail.PCode && x.ProductVersion.StartsWith(outOrderDetail.PVer.Substring(0, 1)) | 
|                             && (isCanLot ? isCanLot : x.ProductCode == outOrderDetail.PLot) | 
|                             && (isCanDate ? isCanDate : x.DateCode == outOrderDetail.DateCode)) | 
|                         .Sum(v => v.StockPcsQty - v.OutboundQuantity)).Sum(x => x); | 
|             //stockInfos = stockInfos.OrderBy(x => x.Id).ToList(); | 
|              | 
|             if (stockTotalQuantity >= needQuantity)//库存够 | 
|             { | 
|                 int index = 0; | 
|                 while (needQuantity > 0) | 
|                 { | 
|                     Dt_ProStockInfo stockInfo = stockInfos[index]; | 
|                     float useableStockQuantity = stockInfo.proStockInfoDetails | 
|                         .Where(x => x.ProductCode == outOrderDetail.PCode && x.ProductVersion.StartsWith(outOrderDetail.PVer.Substring(0,1)) | 
|                             && (isCanLot ? isCanLot : x.ProductCode == outOrderDetail.PLot) | 
|                             && (isCanDate ? isCanDate : x.DateCode == outOrderDetail.DateCode)) | 
|                         .Sum(x => x.StockPcsQty - x.OutboundQuantity); | 
|                     if (useableStockQuantity < needQuantity && useableStockQuantity >0) | 
|                     { | 
|                         stockInfo.proStockInfoDetails.Where(x => x.ProductCode == outOrderDetail.PCode && x.ProductVersion.StartsWith(outOrderDetail.PVer.Substring(0, 1)) | 
|                             && (isCanLot ? isCanLot : x.ProductCode == outOrderDetail.PLot) | 
|                             && (isCanDate ? isCanDate : x.DateCode == outOrderDetail.DateCode)).ToList().ForEach(x => x.OutboundQuantity = x.StockPcsQty); | 
|                         needQuantity -= useableStockQuantity; | 
|                     } | 
|                     else | 
|                     { | 
|                         stockInfo.proStockInfoDetails.ForEach(x => | 
|                         { | 
|                             //满足条件进行分配 | 
|                             if ((x.StockPcsQty > x.OutboundQuantity) | 
|                                 && x.ProductCode == outOrderDetail.PCode && x.ProductVersion.StartsWith(outOrderDetail.PVer.Substring(0, 1))  | 
|                                 && (isCanLot ? isCanLot : x.ProductCode == outOrderDetail.PLot) | 
|                                 && (isCanDate ? isCanDate : x.DateCode == outOrderDetail.DateCode)) | 
|                             { | 
|                                 if (x.StockPcsQty - x.OutboundQuantity >= needQuantity) | 
|                                 { | 
|                                     x.OutboundQuantity += needQuantity; | 
|                                     needQuantity = 0; | 
|                                     x.OutDetailSaleNo = outOrderDetail.SaleOrder; | 
|                                     x.OutDetailId = outOrderDetail.Id; | 
|                                 } | 
|                                 else | 
|                                 { | 
|                                     needQuantity -= (x.StockPcsQty - x.OutboundQuantity); | 
|                                     x.OutboundQuantity = x.StockPcsQty; | 
|                                     x.OutDetailSaleNo = outOrderDetail.SaleOrder; | 
|                                     x.OutDetailId = outOrderDetail.Id; | 
|                                 } | 
|                             } | 
|                         }); | 
|                     } | 
|                     assignOutStocks.Add(stockInfo); | 
|                     index++; | 
|                 } | 
|             } | 
|             #region 成品可用库存不足不进行分配 | 
|             //else | 
|             //{ | 
|             //    for (int i = 0; i < stockInfos.Count; i++) | 
|             //    { | 
|             //        Dt_ProStockInfo stockInfo = stockInfos[i]; | 
|             //        float useableStockQuantity = stockInfo.proStockInfoDetails | 
|             //            .Where(x => x.ProductCode == outOrderDetail.PCode && x.ProductVersion == outOrderDetail.PVer | 
|             //                && (isCanLot ? isCanLot : x.BagNo == outOrderDetail.PLot) | 
|             //                && (isCanDate ? isCanDate : x.DateCode == outOrderDetail.DateCode)) | 
|             //            .Sum(x => x.StockPcsQty - x.OutboundQuantity); | 
|             //        if (useableStockQuantity < needQuantity) | 
|             //        { | 
|             //            stockInfo.proStockInfoDetails.ForEach(x => x.OutboundQuantity = x.StockPcsQty); | 
|             //            needQuantity -= useableStockQuantity; | 
|             //        } | 
|             //        else | 
|             //        { | 
|             //            stockInfo.proStockInfoDetails.ForEach(x => | 
|             //            { | 
|             //                if (x.StockPcsQty > x.OutboundQuantity && x.ProductCode == outOrderDetail.PCode && x.ProductVersion == outOrderDetail.PVer | 
|             //                    && (isCanLot ? isCanLot : x.BagNo == outOrderDetail.PLot) | 
|             //                    && (isCanDate ? isCanDate : x.DateCode == outOrderDetail.DateCode)) | 
|             //                { | 
|             //                    if (x.StockPcsQty - x.OutboundQuantity >= needQuantity) | 
|             //                    { | 
|             //                        x.OutboundQuantity += needQuantity; | 
|             //                        needQuantity = 0; | 
|             //                    } | 
|             //                    else | 
|             //                    { | 
|             //                        needQuantity -= (x.StockPcsQty - x.OutboundQuantity); | 
|             //                        x.OutboundQuantity = x.StockPcsQty; | 
|             //                    } | 
|             //                } | 
|             //            }); | 
|             //        } | 
|             //        stockInfo.proStockInfoDetails.ForEach(x => | 
|             //        { | 
|             //            x.OutDetailSaleNo = outOrderDetail.SaleOrder; | 
|             //            x.OutDetailId = outOrderDetail.Id; | 
|             //        }); | 
|             //        assignOutStocks.Add(stockInfo); | 
|             //    } | 
|             //} | 
|             #endregion | 
|             residueQuantity = needQuantity; | 
|             return assignOutStocks; | 
|         } | 
|         /// <summary> | 
|         /// 获取报废库存 | 
|         /// </summary> | 
|         public List<Dt_ProStockInfo> GetOutboundStocks(List<Dt_ProStockInfo> stockInfos, Dt_ErpProScrapSheetDetail outOrderDetail, float needQuantity, out float residueQuantity) | 
|         { | 
|             List<Dt_ProStockInfo> assignOutStocks = new List<Dt_ProStockInfo>(); | 
|             float stockTotalQuantity = stockInfos.Select(x => x.proStockInfoDetails.Where(x => | 
|                             x.ProductCode == outOrderDetail.ScrapProCode | 
|                             && x.ProductVersion == outOrderDetail.ScrapProVersion | 
|                             && x.LotNumber == outOrderDetail.ScrapProLotNo).Sum(v => v.StockPcsQty - v.OutboundQuantity)).Sum(x => x); | 
|             //stockInfos = stockInfos.OrderBy(x => x.Id).ToList(); | 
|             if (stockTotalQuantity >= needQuantity)//库存够 | 
|             { | 
|                 int index = 0; | 
|                 while (needQuantity > 0) | 
|                 { | 
|                     Dt_ProStockInfo stockInfo = stockInfos[index]; | 
|                     float useableStockQuantity = stockInfo.proStockInfoDetails | 
|                         .Where(x =>  | 
|                             x.ProductCode == outOrderDetail.ScrapProCode  | 
|                             && x.ProductVersion==outOrderDetail.ScrapProVersion | 
|                             && x.LotNumber == outOrderDetail.ScrapProLotNo) | 
|                         .Sum(x => x.StockPcsQty - x.OutboundQuantity); | 
|                     if (useableStockQuantity < needQuantity && useableStockQuantity > 0) | 
|                     { | 
|                         stockInfo.proStockInfoDetails.Where(x =>  | 
|                             x.ProductCode == outOrderDetail.ScrapProCode | 
|                             && x.ProductVersion == outOrderDetail.ScrapProVersion | 
|                             && x.LotNumber == outOrderDetail.ScrapProLotNo).ToList().ForEach(x => x.OutboundQuantity = x.StockPcsQty); | 
|                         needQuantity -= useableStockQuantity; | 
|                     } | 
|                     else | 
|                     { | 
|                         stockInfo.proStockInfoDetails.ForEach(x => | 
|                         { | 
|                             //满足条件进行分配 | 
|                             if ((x.StockPcsQty > x.OutboundQuantity) | 
|                             && x.ProductCode == outOrderDetail.ScrapProCode | 
|                             && x.ProductVersion == outOrderDetail.ScrapProVersion | 
|                             && x.LotNumber == outOrderDetail.ScrapProLotNo) | 
|                             { | 
|                                 if (x.StockPcsQty - x.OutboundQuantity >= needQuantity) | 
|                                 { | 
|                                     x.OutboundQuantity += needQuantity; | 
|                                     needQuantity = 0; | 
|                                     x.OutDetailId = outOrderDetail.Id; | 
|                                 } | 
|                                 else | 
|                                 { | 
|                                     needQuantity -= (x.StockPcsQty - x.OutboundQuantity); | 
|                                     x.OutboundQuantity = x.StockPcsQty; | 
|                                     x.OutDetailId = outOrderDetail.Id; | 
|                                 } | 
|                             } | 
|                         }); | 
|                     } | 
|                     assignOutStocks.Add(stockInfo); | 
|                     index++; | 
|                 } | 
|             } | 
|             residueQuantity = needQuantity; | 
|             return assignOutStocks; | 
|         } | 
|         /// <summary> | 
|         /// 获取MES提库库存 | 
|         /// </summary> | 
|         public List<Dt_ProStockInfo> GetOutboundStocks(List<Dt_ProStockInfo> stockInfos, Dt_MesRworkOutboundOrder mesRworkOutboundOrder, float needQuantity, out float residueQuantity) | 
|         { | 
|             List<Dt_ProStockInfo> assignOutStocks = new List<Dt_ProStockInfo>(); | 
|             bool isCanDate = string.IsNullOrEmpty(mesRworkOutboundOrder.DateCode); | 
|             float stockTotalQuantity = stockInfos.Select(x => x.proStockInfoDetails.Where(x => x.ProductCode == mesRworkOutboundOrder.ProductCode | 
|                             && x.ProductVersion == mesRworkOutboundOrder.ProductVersion | 
|                             && (isCanDate ? isCanDate : x.DateCode == mesRworkOutboundOrder.DateCode)) | 
|                         .Sum(v => v.StockPcsQty - v.OutboundQuantity)).Sum(x => x); | 
|             //stockInfos = stockInfos.OrderBy(x => x.Id).ToList(); | 
|             if (stockTotalQuantity >= needQuantity)//库存够 | 
|             { | 
|                 int index = 0; | 
|                 while (needQuantity > 0) | 
|                 { | 
|                     Dt_ProStockInfo stockInfo = stockInfos[index]; | 
|                     float useableStockQuantity = stockInfo.proStockInfoDetails | 
|                         .Where(x => x.ProductCode == mesRworkOutboundOrder.ProductCode  | 
|                             && x.ProductVersion == mesRworkOutboundOrder.ProductVersion | 
|                             && (isCanDate? isCanDate: x.DateCode == mesRworkOutboundOrder.DateCode)) | 
|                         .Sum(x => x.StockPcsQty - x.OutboundQuantity); | 
|                     if (useableStockQuantity < needQuantity) | 
|                     { | 
|                         stockInfo.proStockInfoDetails.ForEach(x => x.OutboundQuantity = x.StockPcsQty); | 
|                         needQuantity -= useableStockQuantity; | 
|                     } | 
|                     else | 
|                     { | 
|                         stockInfo.proStockInfoDetails.ForEach(x => | 
|                         { | 
|                             if ((x.StockPcsQty > x.OutboundQuantity)  | 
|                                 && x.ProductCode == mesRworkOutboundOrder.ProductCode  | 
|                                 && x.ProductVersion == mesRworkOutboundOrder.ProductVersion | 
|                                 && (isCanDate ? isCanDate : x.DateCode == mesRworkOutboundOrder.DateCode)) | 
|                             { | 
|                                 if (x.StockPcsQty - x.OutboundQuantity >= needQuantity) | 
|                                 { | 
|                                     x.OutboundQuantity += needQuantity; | 
|                                     needQuantity = 0; | 
|                                 } | 
|                                 else | 
|                                 { | 
|                                     needQuantity -= (x.StockPcsQty - x.OutboundQuantity); | 
|                                     x.OutboundQuantity = x.StockPcsQty; | 
|                                 } | 
|                             } | 
|                         }); | 
|                     } | 
|                     assignOutStocks.Add(stockInfo); | 
|                     index++; | 
|                 } | 
|             } | 
|             residueQuantity = needQuantity; | 
|             return assignOutStocks; | 
|         } | 
|         ////处理出库库存 | 
|         //public (List<Dt_ProStockInfoDetail>?, List<Dt_ProStockInfoDetail>?) HandleOutProStock(Dt_ProStockInfo proStockInfo) | 
|         //{ | 
|         //    List<Dt_ProStockInfoDetail>? deleteStockDetails = null; | 
|         //    List<Dt_ProStockInfoDetail>? updateStockDetails = null; | 
|         //    foreach (var item in proStockInfo.proStockInfoDetails) | 
|         //    { | 
|         //        if (item.StockPcsQty==item.OutboundQuantity) | 
|         //        { | 
|         //            item.ProOutDetailStatus = StockStatusEmun.出库完成.ObjToInt(); | 
|         //            deleteStockDetails.Add(item); | 
|         //        } | 
|         //        else if(item.StockPcsQty> item.OutboundQuantity && item.OutboundQuantity>0) | 
|         //        { | 
|         //            item.StockPcsQty-=item.OutboundQuantity; | 
|         //            updateStockDetails.Add(item); | 
|         //        } | 
|         //    } | 
|         //    return (deleteStockDetails, updateStockDetails); | 
|         //} | 
|         public WebResponseContent GetProCodeByWarehouse(int warehouseId) | 
|         { | 
|             try | 
|             { | 
|                 //获取所有库存型号 | 
|                 List<Dt_ProStockInfoDetail> proStockInfoDetails = _stockRepository.ProStockInfoRepository.Db.Queryable<Dt_ProStockInfo, Dt_ProStockInfoDetail>((master, detail) => master.Id == detail.ProStockId) | 
|                 .Where((master, detail) => master.WarehouseId == warehouseId) | 
|                 .Select((master, detail) => detail) | 
|                 .ToList(); | 
|                 //过滤重复 | 
|                 List<string> proCode = proStockInfoDetails.Select(x => x.ProductCode).Distinct().ToList(); | 
|                 return WebResponseContent.Instance.OK("成功",data: proCode); | 
|             } | 
|             catch (Exception ex) | 
|             { | 
|                 return WebResponseContent.Instance.Error(ex.Message); | 
|             } | 
|         } | 
|   | 
|         public WebResponseContent GetProVersionByCode(string scrapProCode, int warehouseId) | 
|         { | 
|             try | 
|             { | 
|                 //获取指定产品库存版本 | 
|                 List<Dt_ProStockInfoDetail> proStockInfoDetails = _stockRepository.ProStockInfoRepository.Db.Queryable<Dt_ProStockInfo, Dt_ProStockInfoDetail>((master, detail) => master.Id == detail.ProStockId) | 
|                 .Where((master, detail) => master.WarehouseId == warehouseId && detail.ProductCode== scrapProCode) | 
|                 .Select((master, detail) => detail) | 
|                 .ToList(); | 
|                 //过滤重复 | 
|                 List<string> productVersion = proStockInfoDetails.Select(x => x.ProductVersion).Distinct().ToList(); | 
|                 return WebResponseContent.Instance.OK("成功",data: productVersion); | 
|             } | 
|             catch (Exception ex) | 
|             { | 
|                 return WebResponseContent.Instance.Error(ex.Message); | 
|             } | 
|         } | 
|   | 
|         public WebResponseContent GetProLotNoByCode(string scrapProCode, int warehouseId) | 
|         { | 
|             try | 
|             { | 
|                 //获取指定产品库存批次 | 
|                 List<Dt_ProStockInfoDetail> proStockInfoDetails = _stockRepository.ProStockInfoRepository.Db.Queryable<Dt_ProStockInfo, Dt_ProStockInfoDetail>((master, detail) => master.Id == detail.ProStockId) | 
|                 .Where((master, detail) => master.WarehouseId == warehouseId && detail.ProductCode == scrapProCode) | 
|                 .Select((master, detail) => detail) | 
|                 .ToList(); | 
|                 //过滤重复 | 
|                 List<string> lotNumber = proStockInfoDetails.Select(x => x.LotNumber).Distinct().ToList(); | 
|                 return WebResponseContent.Instance.OK("成功", data: lotNumber); | 
|             } | 
|             catch (Exception ex) | 
|             { | 
|                 return WebResponseContent.Instance.Error(ex.Message); | 
|             } | 
|         } | 
|     } | 
| } |